27

I've heard many places that PHP's eval function is often not the answer. In light of PHP 5.3's LSB and closures we're running out of reasons to depend on eval or create_function.

Are there any conceivable cases where eval is the best (only?) answer in PHP 5.3?

This question is not about whether eval is evil in general, as it obviously is not.

Summary of Answers:

  • Evaluating numerical expressions (or other "safe" subsets of PHP)
  • Unit testing
  • Interactive PHP "shell"
  • Deserialization of trusted var_export
  • Some template languages
  • Creating backdoors for administers and/or hackers
  • Compatibility with < PHP 5.3
  • Checking syntax (possibly not safe)
Community
  • 1
  • 1
Kendall Hopkins
  • 43,213
  • 17
  • 66
  • 89
  • When you're evaluating a hardcoded string without any variables. Of course, that's not the point of `eval()` ;) – BoltClock Aug 17 '10 at 08:57
  • 2
    After some thought I had to conclude that I really don't know any valid use of `eval` apart from executing compiled code or to build a try-php-code sandbox. Thus I am giving bounty to either conclude that since PHP 5.3 there really isn't any use for `eval` anymore (apart from compilation/sandbox) or to get a good example of where to use it. – NikiC Nov 02 '10 at 16:07
  • Your post is misleading. You have three questions in there. What exactly do you want to know? When is eval not evil? When is eval is the best solution? Or when is eval the only solution? Those are three completely different things. – netcoder Nov 03 '10 at 17:23
  • 2
    @netcoder: they all seem the same to me, more or less. – El Yobo Nov 04 '10 at 21:40
  • 1
    @netcoder All of the questions effectively mean (to me), "When is `eval` the best-practice solution." – Kendall Hopkins Nov 04 '10 at 21:57
  • @nikic There is exactly ONE case where I had to use eval. I had an array with values that had to be passed to a function that accepted any number of arguments but not an array of arguments. Rewriting the function was not an option because it was from a third party lib that is still being updated and I can not rewrite the function after every update. The only solution I ound was using implode(',',$args) and eval. If you know an other sollution I would be more then glad to use it. – Oliver A. Jan 08 '11 at 00:23
  • 2
    @Oliver `call_user_func_array` sounds like it'd work for you. Basically `call_user_func_array( "func", array( $arg1, ... $argn ) )` == `func( $arg1, ... $argn )`. – Kendall Hopkins Jan 08 '11 at 00:31
  • @Kendall Hopkins wow if been working with php for years but I never stumbled upon this one. Maybe because I avoid functions with a undefined number of parameters. Shame on me & thanks a lot. – Oliver A. Jan 08 '11 at 00:37

15 Answers15

19

If you're writing malware and you want to make life hard for the sysadmin who's trying to clean up after you. That seems to be the most common usage case in my experience.

tylerl
  • 30,197
  • 13
  • 80
  • 113
18

Eric Lippert sums eval up over three blog posts. It's a very interesting read.

As far as I'm aware, the following are some of the only reasons eval is used.

For example, when you are building up complex mathematical expressions based on user input, or when you are serializing object state to a string so that it can be stored or transmitted, and reconstituted later.

Kendall Hopkins
  • 43,213
  • 17
  • 66
  • 89
Russell Dias
  • 70,980
  • 5
  • 54
  • 71
  • 2
    Evaluating mathematical expressions (after they have been check for syntactical correctness and made sure to be not malicious) probably really is one of the valid uses for `eval`. Implementing it yourself would be overkill. But for serializing objects you should use PHP's `serialize` function, which is a) faster b) more secure and c) more complete (circular references, ...) – NikiC Nov 04 '10 at 14:42
  • I agree with the `serialize`; this answer was more from a language agnostic point of view. – Russell Dias Nov 04 '10 at 21:18
  • 6
    I'm not sure if I agree that implementing a mathematical expression engine is overkill. If your going to effort of making sure it's valid, it shouldn't be to much more effort to evaluate it. – Kendall Hopkins Nov 04 '10 at 22:01
  • 1
    @Kendall: [Klick (is German, but you should at least understand the code)](https://www.lima-city.de/board/action:jump/941629). The PCRE I use in there maybe is not what you can call trivial to understand, but at least the whole code only takes up three lines. Then I start talking about validating syntactically (even not semantically, that's what the PCRE does!) using the Tokenizer. And only the list of valid tokens alone exceeds the simple regex+eval solution. So, sure, it's far less effort, at least if you are familiar enough with regex. – NikiC Nov 05 '10 at 07:41
  • 1
    Isn't de-fanging the input nearly as hard as (and more dangerous than) just writing an expression evaluator? – Mike Clark Nov 09 '10 at 15:54
  • @Mike: See my post linked in the comment above. – NikiC Nov 09 '10 at 17:02
8

The main problem with eval is it being a gateway for malicious code. Thus you should never use it in a context where it can be exploited from the outside, e.g. user provided input.

One valid UseCase would be in Mocking Frameworks.

Example from PHPUnit_Framework_TestCase::getMock()

// ... some code before

    $mock = PHPUnit_Framework_MockObject_Generator::generate(
      $originalClassName,
      $methods,
      $mockClassName,
      $callOriginalClone,
      $callAutoload
    );

    if (!class_exists($mock['mockClassName'], FALSE)) {
        eval($mock['code']);
    }

// ... some code after

There is actually a lot of things happening in the generate method. In laymens terms: PHPUnit will take the arguments to generate and create a class template from it. It will then eval that class template to make it available for instantiation. The point of this is to have TestDoubles to mock dependencies in UnitTests of course.

Gordon
  • 312,688
  • 75
  • 539
  • 559
4

If you are writing a site that interprets and executes PHP code, like an interactive shell would.

...

I'm a systems guy, that's all I got.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • This kind of application would be hard to sandbox (if possible at all), and would *have* to require admin access to use. If the user is required to have admin access, there is little-to-no reason for them not to just edit a `.php` files directly or fire up `php -a`. – Kendall Hopkins Aug 17 '10 at 06:08
  • @Ken I don't see what "admin access" has to do with anything here. – Artefacto Aug 17 '10 at 06:24
  • http://try-python.mired.org/ http://www.ruby.ch/interpreter/rubyinterpreter.shtml http://blog.arpitnext.com/2009/08/codepad-online-compiler-interpreter-run.html - there are three – Ed S. Aug 20 '10 at 20:50
  • @Ed Swangren Those aren't for PHP. – Kendall Hopkins Nov 02 '10 at 17:39
  • What does that matter? The concept is the same. – Ed S. Nov 02 '10 at 17:57
  • @Mike I question the security of "sandbox" done in PHP. I've noticed that they've disabled a ton of functions, but it would still be easy to DOS it. IMO any website that lets end-users run code on a turing complete machine is asking for trouble. – Kendall Hopkins Nov 02 '10 at 22:56
  • Ok, not really relevant to the question, but ok. – Ed S. Nov 02 '10 at 23:11
4

You can use eval to create ad-hoc classes:

function myAutoLoad($sClassName){

   # classic part
   if (file_exists($sClassName.'.php'){

      require $sClassName.'.php';

    } else {

      eval("
            class $sClassName{
                public function __call($sMethod,$aArgs){
                     return 'No such class: ' . $sClassName;
                 }
                }");

    }

} 

Although, of course, usage is quite limited (some API's or maybe DI containers, testing frameworks, ORMs which have to deal with databases with dynamic structure, code playgrounds)

NikiC
  • 100,734
  • 37
  • 191
  • 225
ts.
  • 10,510
  • 7
  • 47
  • 73
  • 5
    Wouldn't it be better to just throw an exception and use `try`/`catch` block to handle the logic? – Kendall Hopkins Nov 06 '10 at 01:39
  • 1
    -1 for answer because of +1 for Kendall's comment. This seems to be a workaround for bad application design, doesn't it? – NikiC Nov 06 '10 at 09:10
  • exception blocks code execution. If you want to deal ie. with a database with dynamically changing structure it is a way in which application can adapt itself in a runtime. (return with 'no such class ' was only an example; could we think a little more abstract?) – ts. Nov 06 '10 at 09:25
  • @ts: Maybe the example simply is pointless and you should change it to something more realistic ;) Furthermore I don't get how a database may change its structure dynamically (well, I understand it could, but I don't get why it could ever want to do that.) – NikiC Nov 06 '10 at 09:34
  • @nikic: imagine big db which is not under your control, and a horde of apps which are not under your control, and an intermediating API which indeed, is under your control and must adapt itself to changing db structure. When an app calls API using feature which do not exists yet, API extends itself ad hoc, using eval to deal with it - ie. to create new ORM classes. Subtle nuance here is that api script has no direct access to file system, so he can write new file with code directly; instead it uses eval'd code which is also send up and finally ends included into codebase, but it takes time. – ts. Nov 06 '10 at 14:39
  • @nikic: another use is test automation - developers use annotations to mark some basic tests directly in source code. When the code is commited to repository, annotations are parsed and apropriate tests are generated and executed. Of course there is no interest in saving hundreds or thousands files just to reparse them only one time, so all generated code is eval'd. – ts. Nov 06 '10 at 14:50
  • @ts I'm pretty sure this could be done w/ `class_alias` much cleaner. – Kendall Hopkins Nov 08 '10 at 22:33
  • well, I am pretty sure that not. Class_alias is good only when you have one master class which you can use as a replacement. And here I am talking rather about code generation on the fly. Once again: example which i gave is very, very simple. Real production code has bunch of classes and few thousands lines of code. How would you generate multiple test classes with class_alias? – ts. Nov 08 '10 at 23:43
3

eval is a construct that can be used to check for syntax errors.

Say you have these two PHP scripts:

script1.php

<?php
// This is a valid syntax
$a = 1;

script2.php

<?php
// This is an invalid syntax
$a = abcdef

You can check for syntax errors using eval:

$code1 = 'return true; ?>'.file_get_contents('script1.php');
$code2 = 'return true; ?>'.file_get_contents('script2.php');

echo eval($code1) ? 'script1 has valid syntax' : 'script1 has syntax errors';
echo eval($code2) ? 'script2 has valid syntax' : 'script2 has syntax errors';

Unlike php_check_syntax (which is deprecated and removed anyway), the code will not be executed.

EDIT:

The other (preferred) alternative being php -l. You can use the solution above if you don't have access to system() or shell execution commands.

This method can inject classes/functions in your code. Be sure to enforce a preg_replace call or a namespace before doing so, to prevent them from being executed in subsequent calls.

As for the OP topic: When (if ever) is eval NOT evil? eval is simply not evil. Programmers are evil for using eval for no reason. eval can shorten your code (mathematical expression evaluation, per example).

netcoder
  • 66,435
  • 19
  • 125
  • 142
  • This **isn't** safe as the checked string could define a function/class, and it would get injected into the runtime. Also we have `token_get_all` which can do the same thing and doesn't require "running" anything. – Kendall Hopkins Nov 02 '10 at 22:13
  • I never pretended that this was "safe" and could not lead to function/class injection into the runtime. You always have to be careful when using `eval`, in any language. However, as far I am aware, `token_get_all` doesn't tell you whether the syntax is correct or not. – netcoder Nov 02 '10 at 22:23
  • I'd also like to add that if you want to prevent injected classes/functions to be executed or to conflict with your own code, you can `preg_replace` classes and functions names beforehand. And this is pretty much the only solution for checking syntax in 5.3 if a shell execution is not allowed by system settings. – netcoder Nov 02 '10 at 22:36
  • @netcoder Think your solution is clever, but I'd feel much safer implementing `php_check_syntax` using `token_get_all` like this guy did. http://www.php.net/manual/en/function.php-check-syntax.php#87762 – Kendall Hopkins Nov 03 '10 at 03:28
  • Also I'd like to note that your `script2.php` is only invalid because you left off the `;` at the end of the line, *not* because you including a string w/o quotes. That is actually valid (not strict) in PHP. – Kendall Hopkins Nov 03 '10 at 03:36
  • Omitting the semi-colon without providing an end tag triggers a Parse Error. `token_get_all` doesn't give you the syntax errors, `php -l` does. – netcoder Nov 03 '10 at 03:56
  • @netcoder: Please add to your answer, that functions and classes may be injected ;) @netcoder: If you want to check for classes and functions beforehand never shall you use `preg_` for that, but use the Tokenizer instead @topic: Still I don't think this is a legitimate use for `eval`. As they say in the manual, you should use `php -l` for that. – NikiC Nov 03 '10 at 15:39
  • @Kandall: That function doesn't use the Tokenizer to check the source code. Though there are PHP parsers written in PHP I still wouldn't recommend using them. `php -l` is so much easier. – NikiC Nov 03 '10 at 15:41
  • @nikic: As I said in my last edit, `eval` is legitimate as long as it doesn't cause problems (performance, etc.) like ANY other PHP function/construct. If it shortens your code and is used in a safe way, I don't see why it should not be used. `foreach` is as evil as `eval` when used incorrectly, they just don't have the same purpose. – netcoder Nov 03 '10 at 15:57
  • @netcoder: I have yet to find a dangerous use of `foreach`... PS: I (and the OP) are asking here for cases where you could legitimately use `eval`. Lint checks are not one of them, because they are better alternatives. If you think that math expression evaluation is a valid use case, please add another answer ;) – NikiC Nov 03 '10 at 16:03
  • @netcoder You couldn't be more wrong. `foreach` is the safest iteration method in PHP, where `eval` is almost exclusively used as a hack in place of a proper solution. There's a reason `eval` is only one letter off of "evil" :P – Kendall Hopkins Nov 03 '10 at 19:21
  • @Kendall: Your argumentation makes no sense to me. It's not because it's the **safest** that it's 100% safe (i.e.: not dangerous). Comparing safe and evil is like comparing apples and oranges. And please explain why eval is evil before claiming it is. Also, I'd like to know your definition of a "proper solution". – netcoder Nov 03 '10 at 19:42
  • @netcoder When I mean "evil" I mean unsafe, hacky, hard to maintain, etc. Anytime you use `eval` to run user provided code is another place where something could go wrong. For example, if PHP introduces more keywords (in future version) that could possibly do similar things as function/class exploit we talked about. Or if the user submitted code with a `Fatal Error` in it, which would causes the script to stop executing. The reason these problems exist, is because syntax checking is a side effect of `eval` not the intended use. – Kendall Hopkins Nov 04 '10 at 04:01
2

I've found that there are times when most features of a language are useful. After all, even GOTO has had its proponents. Eval is used in a number of frameworks and it is used well. For example, CodeIgniter uses eval to distinguish between class hierarchy of PHP 4 and PHP 5 implementations. Blog plugins which allow for execution of PHP code definitely need it (and that is a feature available in Expression Engine, Wordpress, and others). I've also used it for one website where a series of views are almost identical, but custom code was needed for each and creating some sort of insane rules engine was far more complicated and slower.

While I know that this isn't PHP, I found that Python's eval makes implementation of a basic calculator much simpler.

Basically, here's the question:

  1. Does eval make it easier to read? One of our chief goals is communicating to other programmers what was going through our head when we wrote this. In the CodeIgniter example it is very clear what they were trying to accomplish.
  2. Is there another way? Chances are, if you're using eval (or variable variables, or any other form of string look-up or reflection syntax), there is another way to do it. Have you exhausted your other options? Do you have a reasonably limitted input set? Can a switch statement be used?

Other considerations:

  1. Can it be made safe? Is there a way that a stray piece of code can work its way into the eval statement?
  2. Can it be made consistent? Can you, given an input, always and consistently produce the same output?
cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
1

An appropriate occasion (given the lack of easy alternatives) would be when trusted data was serialized with var_export and it's necessary to unserialize it. Of course, it should never have been serialized in that fashion, but sometimes the error is already done.

Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • 1
    [How to validated the harmlessness of an array string](http://stackoverflow.com/questions/3267951/simulate-php-array-language-construct-or-parse-with-regexp/3268443#3268443) before you `eval` it. – NikiC Nov 02 '10 at 16:01
  • 1
    But I think that you shouldn't call this a valid use of eval. This use results from bad design and thus the best thing you could do it to eval all your data once and properly serialize it. – NikiC Nov 02 '10 at 16:02
1

I suppose, eval should be used where the code is actually needs to be compiled. I mean such cases like template file compilations (template language into PHP for the sake of performance), plugin hook compilation, compilations for performance reasons etc.

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
  • 4
    Most popular templating engines (smarty and twig) have found that it way faster to write the PHP code to a file that way it can take advantage of opcode caching. It'd have to be a pretty crazy templating system to *require* run time building of template code. – Kendall Hopkins Aug 17 '10 at 13:35
  • VBulletin Plugin System and templates are an example of what I've said. – Vladislav Rastrusny Aug 17 '10 at 14:50
  • 1
    @Kendall: Well, that is just `eval` under another name ^^ – NikiC Nov 07 '10 at 15:14
  • @nikic I would argue no. `eval` to me is all about invoking the parser at runtime. While you can say that `require` could be emulated by `eval`, it's a completely different idea. With Twig/Smarty they write out their template .php files and then every other sequential runs tap into those pre-generated templates. While you could do the same with `eval` using `require` is much more strict, as it force the content to remain fairly static... – Kendall Hopkins Nov 07 '10 at 16:35
  • @nikic [continue] In many cases the cached template files are pushed to the production site with locked down permissions. Thus the `eval`-like feature of Twig/Smarty becomes one time code generation, NOT arbitrary code execution. – Kendall Hopkins Nov 07 '10 at 16:35
  • @Kendall: You seem to be preoccupied that eval is evil. At least I have that much trust in Twig to assume that it will not allow arbitrary code execution no matter whether or not I enable the cache (I don't trust Smarty though ^^). Twig/Smarty generally `eval` their code, but offer the possibility to cache it on the hard drive. Thus in this case `include` is just `eval`. – NikiC Nov 07 '10 at 16:50
  • "Twig generally eval their code" this isn't true. While Twig allows for `eval`'ing code that failed to write to a cached file, this isn't the desired option, and is mostly included for convenience/fallback. Performance(sadly) is only reason for Twig to create .php files and then run them. If Twig didn't plan on these generated files being cached, it **wouldn't** go to the effort of translating the Twig template language into PHP, it could just execute it on-the-fly. IMHO this is what separates Twigs `eval`-like functional from raw `eval`. One Time Code Generation != Arbitrary Code Execution. – Kendall Hopkins Nov 07 '10 at 17:22
1

You could use eval to create a setup for adding code after the system installed. Normally if you would want to change the code on the server you would have to add/change existing PHP files. An alternative to this would be to store the code in a database and use eval to execute it. You'd have to be sure that the code added is safe though.

Think of it like a plugin, just one that can do about anything...

You could think of a site that would allow people to contribute code snippets that the users could then dynamically add into their web pages - without them actually persisting code on the webservers filesystem. What you would need is an approval process though...

Knubo
  • 8,333
  • 4
  • 19
  • 25
  • Hm. I really don't like the idea of doing so. Wouldn't it be way cleaner to provide nice APIs to build such plugins (like Facebook does)? Or, to rephrase my question: Do you really do this or is it only a hypothetical idea? – NikiC Nov 06 '10 at 09:12
  • I could imagine myself using eval for something like this. In particular if the runtime settings where the script is run is a read only environment. (Though I haven't had the case where I need to do something like this). I've done this in Javascript though for a Javascript code workshop where you would program a robot in javascript and upload the script to the server. When the robots are to fight, the javascript is dynamically loaded into the browser. The code and everything is present here: javascriptbattle.knubo.no (Afraid the slides we made for this is in Norwegian) – Knubo Nov 06 '10 at 15:13
  • The source code for Javascriptbattle is located here: http://code.google.com/p/javascriptbattle/. (And you will see that the browser is actually using eval() on the downloaded javascript to load the robots) - If you want to try, write your own :) – Knubo Nov 06 '10 at 15:14
1

This eval debate is actually one big misunderstanding in context of php. People are brainwasched about eval being evil, but usually they have no problem using include, although include is essentially the same thing. Include foo is the same as eval file_get_contents foo, so everytime you're including something you commit the mortal sin of eval.

user187291
  • 53,363
  • 19
  • 95
  • 127
  • Except normally PHP doesn't have write access to PHP files it `require` and normally the paths are hardcoded to prevent something like `require( $some_tmp_file )`. `eval` on the other hand takes variables, which like their name suggest can be changed at the drop of a hat. Also `eval` can't tap into the opcode cache of APC and friends which can make it horrible slow. – Kendall Hopkins Nov 06 '10 at 05:38
  • -1 This answer does not relate to the question. Nobody ever said something about eval being evil, we all know this is not true. This is about what you use eval for in PHP 5.3 (and where there is no better solution.) If you do all your includes using `eval(file_get_contents('file.php'))` that's your right, but it doesn't answer the question because there is the better (in the sense of error reporting and shortness) solution `include 'file.php'`. – NikiC Nov 06 '10 at 09:07
  • This. People use eval all the time. Smarty. It rewrites "templates" into php includes, then includes them. It's just eval by another name. And none of the new PHP 5.3 constructs is helpful to avoid it. – mario Nov 06 '10 at 10:15
  • @mario: Sure. Compilation of templates was already mentioned in another answer and got upvoted by me, because it is one of the valid uses for eval. But simply saying eval is not evil doesn't help anyone here. – NikiC Nov 06 '10 at 11:02
  • @nikic: So we're back at not saying eval is not evil? May I ask why the templating answer is more specific for PHP 5.3 though? It seems to be used on < 5.2 too. – mario Nov 06 '10 at 11:21
  • @mario: I would never even think about saying that eval is evil! The difference between your answer and the compilation answer is a simple one: The compilation answer is valid in any version of PHP *including PHP 5.3*, whereas your answer is *not valid in PHP 5.3*. (With "your" answer I refer to marios answer, not to this one.) – NikiC Nov 06 '10 at 11:23
  • I disagree that this should be at -2, but it looks like the reputation detriments have been negated already. – cwallenpoole Nov 09 '10 at 16:26
0

Compatibility. It's quite frequent to provide PHP4 fallbacks. But likewise it's a possible desire to emulate PHP5.4 functionality in 5.3, as example SplString. While simply providing two include variants (include.php4 vs. include.php5) is frequent, it's sometimes more efficient or readable to resort to eval():

 $IMPL_AA = PHP_VERSION >= 5 ? "implements ArrayAccess" : "";
 eval(<<<END
     class BaseFeature $IMPL_AA {

Where in this case the code would work on PHP4, but expose the nicer API/syntax only on PHP5. Note that the example is fictional.

mario
  • 144,265
  • 20
  • 237
  • 291
  • The question explicitly asks for reasons to use `eval` in **PHP 5.3**. That there was much use for `eval` in older version is a well known fact. – NikiC Nov 05 '10 at 07:33
  • The eval is evil meme has no hold regardless of version. The new syntactic sugar in 5.3 doesn't make it a different or non-scripting language by any definition. There was no inherent need for eval in previous versions, like there isn't a sudden non-need since 5.3. – mario Nov 05 '10 at 08:30
  • And btw, Zend Framework 2.0 (the one with the needless namespacing and php5.3 dependency) uses `include("data:,...?>")` for templates; well, with *stream wrappers* actually. Which boils down to an eval by a different name. So many people just don't recognize it conceptually as such. – mario Nov 05 '10 at 08:30
  • This question is not about the "eval is evil meme" per se. This is about the "eval is evil meme" **in PHP 5.3**! In previous versions one simply had to use `eval` and `create_function`; there was no way around, simply because PHP lacked syntax. Since PHP 5.3 things got different. We now have closures, we now have dynamic scope resolution. So I ask you to remove your answer, because, even though it is correct, it does not provide anything to this question. – NikiC Nov 05 '10 at 16:44
  • @Zend Framework 2.0: WTF?!?!? Do they really do this far only not to use the word `eval`? I hope they do know that `data:` inclusion requires `allow_url_include`... – NikiC Nov 05 '10 at 16:46
  • That presumption still looks misguided to me. The use cases for eval weren't any different in PHP<5.2. And closures surely aren't an eval substitute. -- What I'm onto: `include()` is just another name for `eval`, except that it reads from files instead of a string. ZF provides a stream wrapper to parse in rewritten files. So, unless you are avoiding include like the plague, you are effectively still `eval`ing code. Has little to do with the version. – mario Nov 05 '10 at 17:16
  • @mario: The difference is that you normally `include` files that you have written yourself or which are part of some trusted software. `eval` on the other hand is used to evaluate code which was assembled on the fly. That's the basic difference in use. Furthermore please note again, that this thread is not about whether eval is evil (we all know that it is not), this thread is about valid use cases for eval in PHP 5.3. – NikiC Nov 05 '10 at 21:09
  • @nikic: Again you seem to imply that eval is inherently shabby by associating include with "some trusted software" and eval for anything else. But you realize that eval/assert/include/etc. are functionaly-wise equivalent anyway? And again, I don't get your point about PHP5.3. Why exactly should anonymous functions/closures displace **all** eval use cases? PHP5.3 is still PHP. Which is a *scripting language*. – mario Nov 05 '10 at 22:02
  • @mario: Well, how can you not get my point about PHP 5.3? Have you actually read the question? Quote: "Is there is any conceivable cases where eval is the best (only?) answer in PHP 5.3?" I really don't see how your answer relates to the use of `eval` in PHP 5.3. I simply don't see. – NikiC Nov 05 '10 at 22:20
  • @nikic: True. My answer fails to address the fallacy in your question. – mario Nov 05 '10 at 22:54
  • @mario: You seem to think that I am one of those guys who would never every use `eval`, just because it is said to be evil. If you think so, then you are wrong. I simply am looking for examples in this question what you need `eval` for in PHP5.3... – NikiC Nov 06 '10 at 09:04
  • @nikic: Again the fallacy lies in making this specific to a version. None of the answers here is. And I suspect mainly because it makes little sense. – mario Nov 06 '10 at 09:12
  • @mario: No, I (or the OP) have reasons to do so. This is to prevent answers like yours: Answers which relate to lack of features in the language itself. In PHP 5.2 I wouldn't say writing `eval('return ' . $className . '::$foo;')` were wrong, simply because PHP 5.2 doesn't yet have `$className::$foo`... – NikiC Nov 06 '10 at 09:19
  • @nikic: So basically this question is just to reaffirm that you don't need eval anymore for functionality where new language constructs are available for? Well, duh. :) – mario Nov 06 '10 at 10:09
  • @mario: I am honestly starting to get annoyed. The question is what you need eval for in PHP 5.3. Is that so hard to get?!? It is exaclty not about simulating language constructs! – NikiC Nov 06 '10 at 10:59
  • @nikic: Me too. You keep referring to the PHP5.3 tag in your question with **circular logic**. I've asked you twice why 5.3 should have other uses than earlier versions of the very same language. You answered again with 5.3 language constructs. And if that's all your question is about, then you should edit it. But obviously " *Why would I need eval for implementing closures in PHP 5.3 ?* " would be too much of a self-answering question. – mario Nov 06 '10 at 11:09
  • @mario: Even though I have already answered the question I will answer again and again: PHP 5.3 is different, because some uses of eval are no more. I am interested in the remaining. Like compiling, sandboxing, evaluating mathematical expressions. – NikiC Nov 06 '10 at 11:18
  • @nikic: As so it happens I have an answer for these three points. One project of mine http://phpjs.berlios.de/ converts pseudo-Javascript into PHP. It can interpret the AST (more control) or `eval` the generated sandboxed PHP code (more speed). But again, this answer is no more PHP 5.3 specific than the answer above. – mario Nov 06 '10 at 11:24
  • @mario: That's exactly the kind of answer I want to get :) But I think that your point is already well covered by [this answer](http://stackoverflow.com/questions/3499672/when-if-ever-is-eval-not-evil/3500798#3500798), but if you think it is different enough feel free to add another answer. The difference between those two answers is that compilation of code applies to any version of PHP, including PHP 5.3, whereas simulating features in PHP 4 does not apply to PHP 5.3 :) – NikiC Nov 06 '10 at 11:28
  • @nikic: So what is this "not valid in PHP 5.3" in my answer that you get all hung up about? It would parse quite fine in my 5.3.2. Notice that I made my point about emulating PHP 5.4 features in 5.3. – mario Nov 06 '10 at 11:29
  • @mario: Yep, that's it. That what it is all about. If you changed your answer to give an example of which PHP 5.4 features you simulate in PHP 5.3 (and remove the PHP 4 part), then it would be an answer to the question :) – NikiC Nov 06 '10 at 11:33
0

I've used eval when I had a php-engined bot that communicated with me and I could tell it to do commands via EVAL: php commands here. Still evil, but if your code has no idea what to expect (in case you pull a chunk of PHP code from a database) eval is the only solution.

Mikhail
  • 8,692
  • 8
  • 56
  • 82
0

So, this should hold true for all languages with eval:

Basically, with few exceptions, if you are building the value passed to eval or getting it from a non-truested source you are doing something wrong. The same holds true if you are calling eval on a static string.

Beyond the performance problems with initializing the parser at runtime, and the security issues, You generally mess with the type system.

More seriously, it's just been shown that in the vast majority of cases, there are much more elegant approaches to the solution. However, instead of banning the construct outright, it's nice to think of it as one might goto. There are legitimate uses for both, but it is a good red flag that should get you thinking about if you are approaching the problem the correct way.

In my experience, I've only found legitimate uses that fall in the categories of plugins and privileged user (for instance, the administrator of a website, not the user of such) extensions. Basically things that act as code coming from trusted sources.

Arelius
  • 1,216
  • 8
  • 15
0

Not direct use but the /e modifier to preg_replace utilizes eval and can be quite handy. See example #4 on http://php.net/preg_replace.

Whether or not it's evil/bad is subjective and depends entirely on what you consider "good" in a specific context. When dealing with untrusted inputs it is usually considered bad. However, in other situations it can be useful. Imagine writing a one-time data conversion script under extreme deadline pressure. In this situation, if eval works and makes things easier, I would have trouble calling it evil.

llama
  • 26
  • 2
  • Couldn't that be done with `preg_replace_callback` and Closures? I understand the need to hack things together quickly, but the question is about the "best" solution. – Kendall Hopkins Nov 09 '10 at 06:31