Skip to content

Commit

Permalink
Fix #79979: passing value to by-ref param via CUFA crashes
Browse files Browse the repository at this point in the history
If a by-val send is not allowed, we must not do so.  Instead we wrap
the value in a temporary reference.

Closes phpGH-6000
  • Loading branch information
cmb69 committed Aug 24, 2020
1 parent 5ab7b30 commit 6b6c2c0
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 6 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2020, PHP 7.4.11

- Core:
. Fixed bug #79979 (passing value to by-ref param via CUFA crashes). (cmb,
Nikita)

- Calendar:
. Fixed bug #80007 (Potential type confusion in unixtojd() parameter parsing).
(Andy Postnikov)
Expand Down
17 changes: 17 additions & 0 deletions Zend/tests/bug79979.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
Bug #79979 (passing value to by-ref param via CUF(A) crashes)
--FILE--
<?php
call_user_func_array("str_replace", ["a", "b", "c", 0]);

$cufa = "call_user_func_array";
$cufa("str_replace", ["a", "b", "c", 0]);

call_user_func_array($cufa, ["str_replace", ["a", "b", "c", 0]]);
?>
--EXPECTF--
Warning: Parameter 4 to str_replace() expected to be a reference, value given in %s on line %d

Warning: Parameter 4 to str_replace() expected to be a reference, value given in %s on line %d

Warning: Parameter 4 to str_replace() expected to be a reference, value given in %s on line %d
10 changes: 8 additions & 2 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
for (i=0; i<fci->param_count; i++) {
zval *param;
zval *arg = &fci->params[i];
zend_bool must_wrap = 0;

if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
Expand All @@ -765,12 +766,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
ZVAL_NEW_REF(arg, arg);
} else if (!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
/* By-value send is not allowed -- emit a warning,
* but still perform the call with a by-value send. */
* and perform the call with the value wrapped in a reference. */
zend_error(E_WARNING,
"Parameter %d to %s%s%s() expected to be a reference, value given", i+1,
func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
func->common.scope ? "::" : "",
ZSTR_VAL(func->common.function_name));
must_wrap = 1;
if (UNEXPECTED(EG(exception))) {
ZEND_CALL_NUM_ARGS(call) = i;
zend_vm_stack_free_args(call);
Expand All @@ -791,7 +793,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
}

param = ZEND_CALL_ARG(call, i+1);
ZVAL_COPY(param, arg);
if (EXPECTED(!must_wrap)) {
ZVAL_COPY(param, arg);
} else {
ZVAL_NEW_REF(param, arg);
}
}

if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
Expand Down
16 changes: 14 additions & 2 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -5128,6 +5128,7 @@ ZEND_VM_C_LABEL(send_array):
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
zend_bool must_wrap = 0;
if (skip > 0) {
skip--;
continue;
Expand All @@ -5139,6 +5140,7 @@ ZEND_VM_C_LABEL(send_array):
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
must_wrap = 1;
}
}
} else {
Expand All @@ -5148,7 +5150,11 @@ ZEND_VM_C_LABEL(send_array):
arg = Z_REFVAL_P(arg);
}
}
ZVAL_COPY(param, arg);
if (EXPECTED(!must_wrap)) {
ZVAL_COPY(param, arg);
} else {
ZVAL_NEW_REF(param, arg);
}
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
Expand All @@ -5160,12 +5166,14 @@ ZEND_VM_C_LABEL(send_array):
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
zend_bool must_wrap = 0;
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
must_wrap = 1;
}
}
} else {
Expand All @@ -5175,7 +5183,11 @@ ZEND_VM_C_LABEL(send_array):
arg = Z_REFVAL_P(arg);
}
}
ZVAL_COPY(param, arg);
if (EXPECTED(!must_wrap)) {
ZVAL_COPY(param, arg);
} else {
ZVAL_NEW_REF(param, arg);
}
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
Expand Down
16 changes: 14 additions & 2 deletions Zend/zend_vm_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
zend_bool must_wrap = 0;
if (skip > 0) {
skip--;
continue;
Expand All @@ -2083,6 +2084,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
must_wrap = 1;
}
}
} else {
Expand All @@ -2092,7 +2094,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
arg = Z_REFVAL_P(arg);
}
}
ZVAL_COPY(param, arg);
if (EXPECTED(!must_wrap)) {
ZVAL_COPY(param, arg);
} else {
ZVAL_NEW_REF(param, arg);
}
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
Expand All @@ -2104,12 +2110,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
zend_bool must_wrap = 0;
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
must_wrap = 1;
}
}
} else {
Expand All @@ -2119,7 +2127,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_O
arg = Z_REFVAL_P(arg);
}
}
ZVAL_COPY(param, arg);
if (EXPECTED(!must_wrap)) {
ZVAL_COPY(param, arg);
} else {
ZVAL_NEW_REF(param, arg);
}
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
Expand Down

0 comments on commit 6b6c2c0

Please sign in to comment.