summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2016-09-25 12:30:32 +0200
committerNikita Popov <nikic@php.net>2016-09-25 12:39:23 +0200
commitbd893061d68f6bd69a3ecdf29f2be7422cb9336d (patch)
tree1ef3525d8b0647bb974d90caead43ab7975ed5ed
parentdaba342f5713116f211f1b35d23ef471717d4a57 (diff)
downloadphp-git-bd893061d68f6bd69a3ecdf29f2be7422cb9336d.tar.gz
Use SEND_USER for CONST|TMP as well
Otherwise we're missing the "expected to be a reference, value given" warning that appears for ordinary calls to call_user_func(). Also update an UPGRADING note with recent changes wrt call_user_func().
-rw-r--r--UPGRADING6
-rw-r--r--Zend/tests/call_user_func_009.phpt17
-rw-r--r--Zend/zend_compile.c6
-rw-r--r--Zend/zend_vm_def.h12
-rw-r--r--Zend/zend_vm_execute.h71
-rw-r--r--Zend/zend_vm_opcodes.c2
6 files changed, 78 insertions, 36 deletions
diff --git a/UPGRADING b/UPGRADING
index 295f04dd07..5d05a5f469 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -49,9 +49,9 @@ PHP 7.1 UPGRADE NOTES
the notice level only.
. Don't call destructors of incompletely constructed objects, even if they
are kept referenced. See bug #29368 and Zend/tests/bug29368_1.phpt.
- . call_user_func() will now consistently fail to perform calls to functions
- that accept reference arguments. Previously this sometimes worked if
- call_user_func() was used outside a namespace.
+ . call_user_func() will now consistently throw a warning if a function with
+ reference arguments is called. However, call_user_func() will no longer
+ abort the call in this case.
. rand() and srand() are now aliases of mt_rand() and mt_srand().
Consequently the output of the following functions has changed:
. rand()
diff --git a/Zend/tests/call_user_func_009.phpt b/Zend/tests/call_user_func_009.phpt
new file mode 100644
index 0000000000..d45380db15
--- /dev/null
+++ b/Zend/tests/call_user_func_009.phpt
@@ -0,0 +1,17 @@
+--TEST--
+call_user_func() behavior when passing literal to reference parameter
+--FILE--
+<?php
+
+namespace Foo;
+
+var_dump(call_user_func('sort', []));
+var_dump(\call_user_func('sort', []));
+
+?>
+--EXPECTF--
+Warning: Parameter 1 to sort() expected to be a reference, value given in %s on line %d
+bool(true)
+
+Warning: Parameter 1 to sort() expected to be a reference, value given in %s on line %d
+bool(true)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 353cef9579..4978c6c1c9 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3592,12 +3592,8 @@ int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcnam
zend_op *opline;
zend_compile_expr(&arg_node, arg_ast);
- if (arg_node.op_type & (IS_VAR|IS_CV)) {
- opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
- } else {
- opline = zend_emit_op(NULL, ZEND_SEND_VAL, &arg_node, NULL);
- }
+ opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
opline->op2.num = i;
opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, i);
}
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 2d2cd1b158..28a8811b02 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -4716,30 +4716,24 @@ ZEND_VM_C_LABEL(send_array):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, NUM)
+ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM)
{
USE_OPLINE
zval *arg, *param;
zend_free_op free_op1;
SAVE_OPLINE();
- arg = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ arg = GET_OP1_ZVAL_PTR_DEREF(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))) {
- ZVAL_DEREF(arg);
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));
- } else {
- if (Z_ISREF_P(arg) &&
- !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
- /* don't separate references for __call */
- arg = Z_REFVAL_P(arg);
- }
}
+
ZVAL_COPY(param, arg);
FREE_OP1();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index a8cb17e3b8..4cb7e56cb3 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3108,6 +3108,29 @@ send_val_by_ref:
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *arg, *param;
+
+
+ SAVE_OPLINE();
+ arg = EX_CONSTANT(opline->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));
+ }
+
+ ZVAL_COPY(param, arg);
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -12597,6 +12620,30 @@ send_val_by_ref:
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *arg, *param;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+ arg = _get_zval_ptr_tmp(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));
+ }
+
+ ZVAL_COPY(param, arg);
+
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -16078,23 +16125,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN
zend_free_op free_op1;
SAVE_OPLINE();
- arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ arg = _get_zval_ptr_var_deref(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))) {
- ZVAL_DEREF(arg);
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));
- } else {
- if (Z_ISREF_P(arg) &&
- !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
- /* don't separate references for __call */
- arg = Z_REFVAL_P(arg);
- }
}
+
ZVAL_COPY(param, arg);
zval_ptr_dtor_nogc(free_op1);
@@ -35086,23 +35127,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND
SAVE_OPLINE();
- arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ arg = _get_zval_ptr_cv_deref_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))) {
- ZVAL_DEREF(arg);
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));
- } else {
- if (Z_ISREF_P(arg) &&
- !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
- /* don't separate references for __call */
- arg = Z_REFVAL_P(arg);
- }
}
+
ZVAL_COPY(param, arg);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -60131,8 +60166,8 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_SEND_ARRAY_SPEC_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_SEND_USER_SPEC_CONST_HANDLER,
+ ZEND_SEND_USER_SPEC_TMP_HANDLER,
ZEND_SEND_USER_SPEC_VAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_SEND_USER_SPEC_CV_HANDLER,
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index 11e9b1368b..06da751d2e 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -332,7 +332,7 @@ static uint32_t zend_vm_opcodes_flags[187] = {
0x00001001,
0x01000703,
0x00000000,
- 0x00001001,
+ 0x00001003,
0x00000007,
0x00000003,
0x07000003,