]> granicus.if.org Git - php/commitdiff
Revert "Make call_user_func() on reference args consistent"
authorNikita Popov <nikic@php.net>
Thu, 28 Jul 2016 16:45:44 +0000 (18:45 +0200)
committerNikita Popov <nikic@php.net>
Thu, 28 Jul 2016 16:45:44 +0000 (18:45 +0200)
This reverts commit fafe01b07bfcb4f4a9088dd89195f2f5acba8fd0.

See bug #72698, there is code using this behavior. Reverting for
PHP 7.0 *only*. The fix is still in PHP 7.1.

Zend/tests/call_user_func_006.phpt [deleted file]
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/call_user_func_006.phpt b/Zend/tests/call_user_func_006.phpt
deleted file mode 100644 (file)
index 16a59bc..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
---TEST--
-call_user_func() should error on reference arguments
---FILE--
-<?php
-
-namespace Foo;
-
-function bar(&$ref) {
-    $ref = 24;
-}
-
-$x = 42;
-$ref =& $x;
-\call_user_func('Foo\bar', $x);
-var_dump($x);
-
-$y = 42;
-$ref =& $y;
-call_user_func('Foo\bar', $y);
-var_dump($y);
-
-?>
---EXPECTF--
-Warning: Parameter 1 to Foo\bar() expected to be a reference, value given in %s on line %d
-int(42)
-
-Warning: Parameter 1 to Foo\bar() expected to be a reference, value given in %s on line %d
-int(42)
index e4fd8e8e2805d04071f38eb92e6b2cdd7f1a3b72..504bf5783bf6cbb9bd23f6c02f5b1742c438f515 100644 (file)
@@ -4660,27 +4660,32 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
        arg = GET_OP1_ZVAL_PTR(BP_VAR_R);
        param = ZEND_CALL_VAR(EX(call), opline->result.var);
 
-       if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
-               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
-                       opline->op2.num,
-                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
-                       EX(call)->func->common.scope ? "::" : "",
-                       ZSTR_VAL(EX(call)->func->common.function_name));
+       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
+               if (UNEXPECTED(!Z_ISREF_P(arg))) {
+                       if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
 
-               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
-                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
-               }
-               if (Z_OBJ(EX(call)->This)) {
-                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
-               }
-               ZVAL_UNDEF(param);
-               EX(call)->func = (zend_function*)&zend_pass_function;
-               EX(call)->called_scope = NULL;
-               Z_OBJ(EX(call)->This) = NULL;
-               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+                               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
+                                       opline->op2.num,
+                                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
+                                       EX(call)->func->common.scope ? "::" : "",
+                                       ZSTR_VAL(EX(call)->func->common.function_name));
 
-               FREE_OP1();
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
+                                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
+                               }
+                               if (Z_OBJ(EX(call)->This)) {
+                                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
+                               }
+                               ZVAL_UNDEF(param);
+                               EX(call)->func = (zend_function*)&zend_pass_function;
+                               EX(call)->called_scope = NULL;
+                               Z_OBJ(EX(call)->This) = NULL;
+                               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+
+                               FREE_OP1();
+                               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                       }
+               }
        } else {
                if (Z_ISREF_P(arg) &&
                    !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
index 0103128183e17fa720e013e879aca9712c715ab9..b6375908b0ea9d7ce127a789a1b8367db253efdf 100644 (file)
@@ -15371,27 +15371,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN
        arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
        param = ZEND_CALL_VAR(EX(call), opline->result.var);
 
-       if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
-               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
-                       opline->op2.num,
-                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
-                       EX(call)->func->common.scope ? "::" : "",
-                       ZSTR_VAL(EX(call)->func->common.function_name));
+       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
+               if (UNEXPECTED(!Z_ISREF_P(arg))) {
+                       if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
 
-               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
-                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
-               }
-               if (Z_OBJ(EX(call)->This)) {
-                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
-               }
-               ZVAL_UNDEF(param);
-               EX(call)->func = (zend_function*)&zend_pass_function;
-               EX(call)->called_scope = NULL;
-               Z_OBJ(EX(call)->This) = NULL;
-               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+                               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
+                                       opline->op2.num,
+                                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
+                                       EX(call)->func->common.scope ? "::" : "",
+                                       ZSTR_VAL(EX(call)->func->common.function_name));
 
-               zval_ptr_dtor_nogc(free_op1);
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
+                                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
+                               }
+                               if (Z_OBJ(EX(call)->This)) {
+                                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
+                               }
+                               ZVAL_UNDEF(param);
+                               EX(call)->func = (zend_function*)&zend_pass_function;
+                               EX(call)->called_scope = NULL;
+                               Z_OBJ(EX(call)->This) = NULL;
+                               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+
+                               zval_ptr_dtor_nogc(free_op1);
+                               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                       }
+               }
        } else {
                if (Z_ISREF_P(arg) &&
                    !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
@@ -28992,26 +28997,31 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND
        arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
        param = ZEND_CALL_VAR(EX(call), opline->result.var);
 
-       if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
-               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
-                       opline->op2.num,
-                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
-                       EX(call)->func->common.scope ? "::" : "",
-                       ZSTR_VAL(EX(call)->func->common.function_name));
+       if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
+               if (UNEXPECTED(!Z_ISREF_P(arg))) {
+                       if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
 
-               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
-                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
-               }
-               if (Z_OBJ(EX(call)->This)) {
-                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
-               }
-               ZVAL_UNDEF(param);
-               EX(call)->func = (zend_function*)&zend_pass_function;
-               EX(call)->called_scope = NULL;
-               Z_OBJ(EX(call)->This) = NULL;
-               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+                               zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
+                                       opline->op2.num,
+                                       EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
+                                       EX(call)->func->common.scope ? "::" : "",
+                                       ZSTR_VAL(EX(call)->func->common.function_name));
 
-               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                               if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
+                                       OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
+                               }
+                               if (Z_OBJ(EX(call)->This)) {
+                                       OBJ_RELEASE(Z_OBJ(EX(call)->This));
+                               }
+                               ZVAL_UNDEF(param);
+                               EX(call)->func = (zend_function*)&zend_pass_function;
+                               EX(call)->called_scope = NULL;
+                               Z_OBJ(EX(call)->This) = NULL;
+                               ZEND_SET_CALL_INFO(EX(call), ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+
+                               ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+                       }
+               }
        } else {
                if (Z_ISREF_P(arg) &&
                    !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {