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) {
}
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,