diff options
author | Xinchen Hui <laruence@php.net> | 2015-03-03 17:34:45 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2015-03-03 18:11:56 +0800 |
commit | 7ad6711a4dcb092e2125d36ec623f38a22153e73 (patch) | |
tree | 2b75d67091dbdb74a16d429e3500bcd4cb0cb9da | |
parent | 70bd500645da48f3c2eb2ebbe916a2abe51a48e0 (diff) | |
download | php-git-7ad6711a4dcb092e2125d36ec623f38a22153e73.tar.gz |
Fixed bug #69167 (call_user_func does not support references anymore)
-rw-r--r-- | Zend/tests/bug69167.phpt | 17 | ||||
-rw-r--r-- | Zend/zend_API.c | 11 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 4 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 12 |
4 files changed, 42 insertions, 2 deletions
diff --git a/Zend/tests/bug69167.phpt b/Zend/tests/bug69167.phpt new file mode 100644 index 0000000000..79326ed583 --- /dev/null +++ b/Zend/tests/bug69167.phpt @@ -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 diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 693a8340f8..88687796cc 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2e9ffd6448..497f76d666 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 465ecc6dd4..c4bd7b7d0a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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); |