Re: Proposal to deprecate create_function()

From: Date: Fri, 18 Oct 2013 10:39:58 +0000
Subject: Re: Proposal to deprecate create_function()
References: 1 2  Groups: php.internals 
Request: Send a blank email to [email protected] to get a copy of this message
Am 18.10.2013 11:26, schrieb Nikita Popov:
On Mon, Oct 14, 2013 at 11:33 PM, Rowan Collins <[email protected]>wrote:
Hi All, (First, a quick aside: I'm new here, so let me know if I'm treading on any toes or failing to do my homework properly. Also, apologies for long-windedness; it's a personal flaw.) I would like to propose that create_function() be officially deprecated, to encourage people to use the much safer and more powerful anonymous functions we've had since 5.3, and eventually allow this relic to be removed from the language. In case any of you aren't familiar with the details, create_function, according to Zeev's comment in the source "Creates an anonymous function, and returns its name (funny, eh?)". It does this by wrapping some boilerplate around two strings provided by the user, and eval()ing the result to (hopefully) create a function called __lambda_func; it then renames this to a unique name beginning with a null byte, so that it can't conflict with any "real" functions, and returns the new name as a string. Until PHP 5.3, this was the only way to dynamically create a callback function, and is thus a widely used feature, so it should not be removed in a hurry. Many projects (e.g. Wordpress) still support PHP 5.2, so cannot switch over to true anonymous functions yet; but we can hope that most people will have abandoned 5.2 by the time 5.7 or 5.8 comes around, and re-evaluate then. The argument for deprecating it is largely the same as for the /e modifier in preg_replace - namely that it's a wrapper around eval(), with all the dangers that brings. In fact, I've seen a few people trying to "fix" uses of preg_replace using create_function() to create the argument for preg_replace_callback()! Specifically: * It performs absolutely no checks before eval()ing the string. It is
    therefore trivial for code to end up injected into it, and even be
    run immediately, e.g. create_function('', '} echo "hi"; if (0) {');
    [http://3v4l.org/YtmVT]
* Since the function body is simply a string, the only way to "close
    over" a variable is to use var_export, serialize, or similar. Even
    string variables need careful escaping.
* The function name it creates, although guaranteed unique, is
    entirely predictable, and the function exists in the global
    namespace. It's impossible to truly isolate it to a particular scope.
* The function, once created, is never destroyed, so repeated use of
    create_function "leaks" memory.
A seeming alternative to deprecating it would be to reimplement it in terms of closures. However, this would be the worst of both worlds: on the one hand, it would still need to eval() its body argument, so have much the same security risk; on the other, it would still represent a BC break, because it would have a different return type. It is, for instance, possible to reference one "anonymous" function within another, by judicious use of var_export or similar to inject the null-prefixed string into the function body; I doubt anyone heavily uses such tricks, but if they did, create_function() returning a closure object would be more irritating than it not existing at all. I mentioned in StackOverflow chat that the documentation still had examples using create_function, and NikiC went ahead and fixed several, as well as adding a warning to the top of the documentation page. [ https://github.com/salathe/**phpdoc-en/commit/** 1d57b16e69dfd8d93dd6e4a354d3ed**20bd21494d<https://github.com/salathe/phpdoc-en/commit/1d57b16e69dfd8d93dd6e4a354d3ed20bd21494d> ]. I think it would be sensible to take this a step further and emit an E_DEPRECATED message if it is used in PHP 5.6, and add to the warning that it may be removed in a future version of PHP. If anyone can think of any counter-arguments - and in particular, any uses of create_function() which can't trivially be replaced with either a true closure or a direct call to eval() - I would be interested to hear them. Regards,
I'm +1 on deprecating create_function. It is a security liability, it is slow and it eats memory. We have better alternatives nowadays (anonymous functions) and in cases where you need wide-range version support (including PHP 5.2 or lower) you are still better off using a normal, named function rather than create_function. You can even replicate the exact behavior (minus the hiding from get_defined_functions) with just four lines of code (though I have no idea what you could possibly need this for): function create_function($params, $code) {
     static $i = 0;
     $name = "create_function_" . $i++;
     eval("function $name($params) { $code }");
     return $name;
} I tried to look on Github what people currently use create_function for, but with little success. Nearly all results I get are uses in the php testsuite (copied over to various projects). The only other use case I saw was in conjunction with the WordPress add_action() function. In this case the create_function call could always be replaced directly with an anonymous function (i.e. it didn't need any magic create_function capabilities). Nikita Hello,
shure all things can be replaced with more and verbose code. What is the benefit of writing all this lines in contrast to one method call? https://github.com/phpcr/phpcr-utils/blob/master/src/PHPCR/Util/Console/Helper/PhpcrCliHelper.php#L111 -1 for removing wrappers/abbreviations/and such +1 for bugfixing Best, CC

Thread (33 messages)

« previous php.internals (#69666) next »