]> granicus.if.org Git - php/commitdiff
Fixed bug #69167 (call_user_func does not support references anymore)
authorXinchen Hui <laruence@php.net>
Tue, 3 Mar 2015 09:34:45 +0000 (17:34 +0800)
committerXinchen Hui <laruence@php.net>
Tue, 3 Mar 2015 10:11:56 +0000 (18:11 +0800)
Zend/tests/bug69167.phpt [new file with mode: 0644]
Zend/zend_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug69167.phpt b/Zend/tests/bug69167.phpt
new file mode 100644 (file)
index 0000000..79326ed
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #69167 (call_user_func does not support references anymore)
+--FILE--
+<?php
+function l($m) {
+           echo $m . "\n";
+}
+$cb = 'l';
+call_user_func($cb, 'hi');
+$cb2 = &$cb;
+call_user_func($cb2, 'hi2');
+?>
+--EXPECT--
+hi
+hi2
index 693a8340f8ccce25f59c4485b60a46ee0a574d7f..88687796cc10a5b0a7945cfd86f8d8d23fe07abb 100644 (file)
@@ -3017,6 +3017,7 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
                return 0;
        }
 
+again:
        switch (Z_TYPE_P(callable)) {
                case IS_STRING:
                        if (object) {
@@ -3160,7 +3161,6 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
                                }
                        }
                        return 0;
-
                case IS_OBJECT:
                        if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) {
                                fcc->called_scope = fcc->calling_scope;
@@ -3174,7 +3174,14 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint
                                return 1;
                        }
                        /* break missing intentionally */
-
+                       if (callable_name) {
+                               *callable_name = zval_get_string(callable);
+                       }
+                       if (error) zend_spprintf(error, 0, "no array or string given");
+                       return 0;
+               case IS_REFERENCE:
+                       callable = Z_REFVAL_P(callable);
+                       goto again;
                default:
                        if (callable_name) {
                                *callable_name = zval_get_string(callable);
index 2e9ffd6448f58c380700ae318a3e64dd9dca8b00..497f76d6665820f89e97aace12553cc4a05117b4 100644 (file)
@@ -2735,6 +2735,10 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
        zend_class_entry *called_scope;
        zend_object *object;
 
+       if (OP2_TYPE & (IS_VAR|IS_CV)) {
+               ZVAL_DEREF(function_name);
+       }
+
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                if (error) {
                        efree(error);
index 465ecc6dd45fcd28cba5ed89b304b4fc2a31e461..c4bd7b7d0a541e194a86f69b700030253195a39b 100644 (file)
@@ -4587,6 +4587,10 @@ static int ZEND_FASTCALL  ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
        zend_class_entry *called_scope;
        zend_object *object;
 
+       if (IS_CONST & (IS_VAR|IS_CV)) {
+               ZVAL_DEREF(function_name);
+       }
+
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                if (error) {
                        efree(error);
@@ -7492,6 +7496,10 @@ static int ZEND_FASTCALL  ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_
        zend_class_entry *called_scope;
        zend_object *object;
 
+       if (IS_CV & (IS_VAR|IS_CV)) {
+               ZVAL_DEREF(function_name);
+       }
+
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                if (error) {
                        efree(error);
@@ -8646,6 +8654,10 @@ static int ZEND_FASTCALL  ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPC
        zend_class_entry *called_scope;
        zend_object *object;
 
+       if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) {
+               ZVAL_DEREF(function_name);
+       }
+
        if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
                if (error) {
                        efree(error);