mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
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().
This commit is contained in:
parent
daba342f57
commit
bd893061d6
@ -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()
|
||||
|
17
Zend/tests/call_user_func_009.phpt
Normal file
17
Zend/tests/call_user_func_009.phpt
Normal file
@ -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)
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -332,7 +332,7 @@ static uint32_t zend_vm_opcodes_flags[187] = {
|
||||
0x00001001,
|
||||
0x01000703,
|
||||
0x00000000,
|
||||
0x00001001,
|
||||
0x00001003,
|
||||
0x00000007,
|
||||
0x00000003,
|
||||
0x07000003,
|
||||
|
Loading…
Reference in New Issue
Block a user