Skip to content

Commit bba66f9

Browse files
committed
Add mode for verifying internal function params
1 parent a7e84e2 commit bba66f9

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

Zend/zend_execute.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4558,6 +4558,44 @@ ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named
45584558
zend_array_release(extra_named_params);
45594559
}
45604560

4561+
/* Replace optional parameters that weren't passed with their declared default values,
4562+
* which allows us to check that this does not change the behavior of the function. */
4563+
#define ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS 1
4564+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
4565+
static void zend_verify_internal_param_defaults(zend_execute_data **call_ptr) {
4566+
zend_function *fbc = (*call_ptr)->func;
4567+
uint32_t num_passed_args = ZEND_CALL_NUM_ARGS(*call_ptr);
4568+
if (num_passed_args < fbc->common.required_num_args) {
4569+
/* This is an error anyway. */
4570+
return;
4571+
}
4572+
4573+
uint32_t num_declared_args = fbc->common.num_args;
4574+
while (num_passed_args < num_declared_args) {
4575+
zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[num_passed_args];
4576+
zval default_value;
4577+
if (zend_get_default_from_internal_arg_info(&default_value, arg_info) == FAILURE) {
4578+
/* Default value not available, so we can't pass any further defaults either. */
4579+
return;
4580+
}
4581+
4582+
if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
4583+
zval_update_constant_ex(&default_value, fbc->common.scope);
4584+
}
4585+
4586+
zend_vm_stack_extend_call_frame(call_ptr, num_passed_args, 1);
4587+
zval *arg = ZEND_CALL_VAR_NUM(*call_ptr, num_passed_args);
4588+
ZVAL_COPY_VALUE(arg, &default_value);
4589+
if (ARG_SHOULD_BE_SENT_BY_REF(fbc, num_passed_args + 1)) {
4590+
ZVAL_MAKE_REF(arg);
4591+
}
4592+
4593+
num_passed_args++;
4594+
ZEND_CALL_NUM_ARGS(*call_ptr)++;
4595+
}
4596+
}
4597+
#endif
4598+
45614599
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
45624600
/* Special versions of functions that sets EX(opline) before calling zend_vm_stack_extend() */
45634601
static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */

Zend/zend_vm_def.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3886,8 +3886,11 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
38863886
zval retval;
38873887

38883888
SAVE_OPLINE();
3889-
EX(call) = call->prev_execute_data;
3889+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
3890+
zend_verify_internal_param_defaults(&call);
3891+
#endif
38903892

3893+
EX(call) = call->prev_execute_data;
38913894
call->prev_execute_data = execute_data;
38923895
EG(current_execute_data) = call;
38933896

Zend/zend_vm_execute.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,8 +1219,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV
12191219
zval retval;
12201220

12211221
SAVE_OPLINE();
1222-
EX(call) = call->prev_execute_data;
1222+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
1223+
zend_verify_internal_param_defaults(&call);
1224+
#endif
12231225

1226+
EX(call) = call->prev_execute_data;
12241227
call->prev_execute_data = execute_data;
12251228
EG(current_execute_data) = call;
12261229

@@ -1280,8 +1283,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV
12801283
zval retval;
12811284

12821285
SAVE_OPLINE();
1283-
EX(call) = call->prev_execute_data;
1286+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
1287+
zend_verify_internal_param_defaults(&call);
1288+
#endif
12841289

1290+
EX(call) = call->prev_execute_data;
12851291
call->prev_execute_data = execute_data;
12861292
EG(current_execute_data) = call;
12871293

0 commit comments

Comments
 (0)