diff options
author | Nikita Popov <nikic@php.net> | 2016-09-25 12:30:32 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2016-09-25 12:39:23 +0200 |
commit | bd893061d68f6bd69a3ecdf29f2be7422cb9336d (patch) | |
tree | 1ef3525d8b0647bb974d90caead43ab7975ed5ed | |
parent | daba342f5713116f211f1b35d23ef471717d4a57 (diff) | |
download | php-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-- | UPGRADING | 6 | ||||
-rw-r--r-- | Zend/tests/call_user_func_009.phpt | 17 | ||||
-rw-r--r-- | Zend/zend_compile.c | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 12 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 71 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 2 |
6 files changed, 78 insertions, 36 deletions
@@ -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, |