ID:               48693
 Updated by:       fel...@php.net
 Reported By:      peter at lvp-media dot com
-Status:           Assigned
+Status:           Closed
 Bug Type:         Scripting Engine problem
 Operating System: n/a
 PHP Version:      5.3CVS-2009-06-25 (snap)
 Assigned To:      felipe


Previous Comments:
------------------------------------------------------------------------

[2009-06-28 01:22:51] fel...@php.net

This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

I've committed the patch 2 (slightly modified) in 5.2 and HEAD.
5.3 in soon.

Thanks.

------------------------------------------------------------------------

[2009-06-25 13:52:59] peter at lvp-media dot com

The reproduce code got cut off, the else{} should be in the comment
right behind the $borked-assignment.

<?php
$borked = create_function ('', 'return 1; } else {}'); // parse error
$foo    = create_function ('', 'return 1;');

echo $foo ();
?>

------------------------------------------------------------------------

[2009-06-25 13:46:51] peter at lvp-media dot com

Description:
------------
When creating a new lambda function using create_function, any code
behind an extra right curly brace (which closes the function) gets
executed. This is known and expected behaviour of eval, so no problem so
far. However, when the function itself does not contain parsing errors,
while the code after it does, the function gets created (and becomes
available) while zend_eval_stringl() returns false. Therefore the
function's name, defaulting to LAMBDA_TEMP_FUNCNAME, will not be changed
and any future calls to create_functions will fail using a fatal error
("Cannot redeclare __lambda_func()"). Reproduce code is included.

The echo should output "1", however, the fatal error gets thrown
instead. While this absolutely isn't a problem that (should) occur very
often, fixing it seemed fairly easy so I created two patches.

The first patch checks whether any function named LAMBDA_TEMP_FUNCNAME
exists if zend_eval_stringl() fails, and if it does, renames it to
lambda_%d as would be done if the eval succeeded. After all, the
function itself was fine, so the function name can be returned as well.
zend_eval_stringl() outputs the parse error automatically so the
script-owner gets informed of the problem as well. The second patch is
easier, it simply removes any function called LAMBDA_TEMP_FUNCNAME if it
exists.

PATCH 1:

--- zend_builtin_functions.c    2009-06-25 15:23:45.000000000 +0200
+++ zend_builtin_functions_new.c        2009-06-25 15:40:34.000000000
+0200
@@ -1737,8 +1737,8 @@ ZEND_FUNCTION(create_function)
        efree(eval_name);

-       if (retval==SUCCESS) {
+       if (retval==SUCCESS || zend_hash_find(EG(function_table),
LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **)
&func)!=FAILURE) {
                zend_function new_function, *func;

-               if (zend_hash_find(EG(function_table),
LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **)
&func)==FAILURE) {
+               if (retval==SUCCESS &&
zend_hash_find(EG(function_table), LAMBDA_TEMP_FUNCNAME,
sizeof(LAMBDA_TEMP_FUNCNAME), (void **) &func)==FAILURE) {
                        zend_error(E_ERROR, "Unexpected inconsistency
in create_function()");
                        RETURN_FALSE;

PATCH 2:

--- zend_builtin_functions.c            2009-06-25 15:23:45.000000000
+0200
+++ zend_builtin_functions_new.c        2009-06-25 15:23:45.000000000
+0200
@@ -1756,4 +1756,7 @@ ZEND_FUNCTION(create_function)
                RETURN_STRINGL(function_name, function_name_length,
0);
        } else {
+                if (zend_hash_find(EG(function_table),
LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME), (void **)
&func)!=FAILURE) {
+                       zend_hash_del(EG(function_table),
LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME));
+               }
                RETURN_FALSE;
        }

Reproduce code:
---------------
<?php
$borked = create_function ('', 'return 1; } else {}'); // unexpected
else {}
$foo    = create_function ('', 'return 1;');

echo $foo ();
?>

Expected result:
----------------
1

Actual result:
--------------
Fatal error: Cannot redeclare __lambda_func() (previously declared in
/home/peter/test.php(2) : runtime-created function:


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=48693&edit=1

Reply via email to