3 ms·
or just distribute an upgrader with the next release. I'm sure it's more complicated than just find and replace, but the interpreter has a perfectly good parser
by jfoutz 12y ago
or just distribute an upgrader with the next release. I'm sure it's more complicated than just find and replace, but the interpreter has a perfectly good parser right there. eval is impossible (or very hard), but it's pretty legit to error out in that case.
- chriswarbo 12y agoIt's not legit to error-out for eval, since PHP has all kinds of eval-like things. For example, PHP has two namespaces for functions: anonymous functions live in the regular variable namespace, so they can be passed around directly. Named (AKA global) functions are completely separate, so we can't pass them around as values. For example: $my_anon = function() {}; function my_named() {} // Valid array_map($my_anon, []); // Invalid array_map(my_named, []); As a workaround, whenever PHP sees a string when it's expecting a function, it will try to find a global function with a name matching the contents of the string. In other words, we can do: // Valid array_map('my_named', []); This is basically a weak form of eval: taking a string of PHP code ('my_named') and getting back the value it evaluates to (the my_named function). If you error-out for eval, you have to error-out for this, since the content of strings is runtime information and there's no way you can infer it well enough. For example: function smart_replace() { $args = func_get_args(); $func = array_shift($args)? 'str' : 'preg'; return call_user_func_array("{$func}_replace", $args); } Other eval-like things in PHP include variable property lookups, variable method calls and "variable variables": $foo = "hello"; $object1->$foo = $object2->$foo; // Sets $object1's "hello" property to $object2's $object3->$foo(); // Calls $object3's "hello" method $bar = "foo"; echo $$bar; // Outputs hello One interesting fact about these features is that, since they're not as powerful as a real eval, it can often be perfectly safe to supply them with unvalidated user input: array_map('str_' . $_GET['string_function'], $my_array); There's no way we can swap out things like this reliably, and remember that these are not just "crazy uses of eval", they're officially sanctioned ways of working, which in some cases (eg. function names in strings) have no alternatives (short of redefining your own standard library).
- aruggirello 12y agoYou're talking about the very things that make PHP flexible. I don't see how 'swapping out' things like these would make PHP any safer, faster, or easier to read. C/C++ function decorators, or dynamic programming constructs are not exactly that clearer.
- chriswarbo 12y agoNobody's talking about "swapping out" the eval-like features. The parent was saying we could swap out all usages of 'old fashioned' functions like str_replace for some 'new fashioned' alternative, like String::replace, using some kind of upgrader tool. I was pointing out that the PHP's eval-like features make it difficult for any such tool to exist. In particular, with Python or Javascript we might spit out a warning "Eval spotted; this upgrade might not work!". If we did the same in PHP, everyone would get a warning! "String used as function detected; this upgrade might not work!", "Variable variable detected; this upgrade might not work!", and so on.
- jfoutz 12y agoThat's really helpful and insightful. I had specifically avoided mentioning dataflow analysis, I still think a lot of progress could be made with that approach. Essentially modify the interpreter to run every branch, both the true and false clauses of if, and note what strings have what value at that point of execution. in your final example, you can replace the map with a big case switch of all known functions and an error clause. That's of course, a lot of work. I'd guess it's just not worth it.