Skip to content

Commit

Permalink
Correctly report failure in zend_handle_undef_args()
Browse files Browse the repository at this point in the history
And do the check before increfing the closure object, otherwise
we'd have to release it as well.

Fixes oss-fuzz #25313.
  • Loading branch information
nikic committed Aug 31, 2020
1 parent e81becc commit 061c708
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 11 deletions.
9 changes: 9 additions & 0 deletions Zend/tests/named_params/call_user_func.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ $test_variadic = function(...$args) {
$test_ref = function(&$ref) {
$ref++;
};
$test_required = function($a, $b) {
echo "a = $a, b = $b\n";
};

class Test {
public function __construct($a = 'a', $b = 'b', $c = 'c') {
Expand All @@ -31,6 +34,11 @@ call_user_func($test, c: 'C');
call_user_func($test_variadic, 'A', c: 'C');
call_user_func($test_ref, ref: null);
var_dump(call_user_func('call_user_func', $test, c: 'D'));
try {
call_user_func($test_required, b: 'B');
} catch (ArgumentCountError $e) {
echo $e->getMessage(), "\n";
}
try {
var_dump(call_user_func('array_slice', [1, 2, 3, 4, 5], length: 2));
} catch (ArgumentCountError $e) {
Expand Down Expand Up @@ -74,6 +82,7 @@ array(2) {
Warning: {closure}(): Argument #1 ($ref) must be passed by reference, value given in %s on line %d
a = a, b = b, c = D
NULL
{closure}(): Argument #1 ($a) not passed
array_slice(): Argument #2 ($offset) not passed
array(2) {
[3]=>
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -4491,6 +4491,7 @@ ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *cal
start_fake_frame(call, opline);
zend_argument_error(zend_ce_argument_count_error, i + 1, "not passed");
end_fake_frame(call);
return FAILURE;
}
}

Expand Down
22 changes: 11 additions & 11 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -839,17 +839,6 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
} ZEND_HASH_FOREACH_END();
}

if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
uint32_t call_info;

GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info = ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
}
ZEND_ADD_CALL_FLAG(call, call_info);
}

if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF)) {
if (zend_handle_undef_args(call) == FAILURE) {
zend_vm_stack_free_args(call);
Expand All @@ -861,6 +850,17 @@ zend_result zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_
}
}

if (UNEXPECTED(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
uint32_t call_info;

GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
call_info = ZEND_CALL_CLOSURE;
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
}
ZEND_ADD_CALL_FLAG(call, call_info);
}

orig_fake_scope = EG(fake_scope);
EG(fake_scope) = NULL;
if (func->type == ZEND_USER_FUNCTION) {
Expand Down

0 comments on commit 061c708

Please sign in to comment.