From 8a750bb892f008e72e0ca484600dd96ede195d32 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Thu, 5 Sep 2024 23:04:00 +0200 Subject: [PATCH] internal-default-verification --- Zend/zend_execute.c | 38 ++++++++++++++++++++++++++++++++++++++ Zend/zend_vm_def.h | 3 +++ Zend/zend_vm_execute.h | 18 ++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 42f8d46d5a3d..58d858abb566 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4888,6 +4888,44 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o } /* }}} */ +/* Replace optional parameters that weren't passed with their declared default values, + * which allows us to check that this does not change the behavior of the function. */ +#define ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS 1 +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +static void zend_verify_internal_param_defaults(zend_execute_data **call_ptr) { + zend_function *fbc = (*call_ptr)->func; + uint32_t num_passed_args = ZEND_CALL_NUM_ARGS(*call_ptr); + if (num_passed_args < fbc->common.required_num_args) { + /* This is an error anyway. */ + return; + } + + uint32_t num_declared_args = fbc->common.num_args; + while (num_passed_args < num_declared_args) { + zend_internal_arg_info *arg_info = (zend_internal_arg_info *)&fbc->internal_function.arg_info[num_passed_args]; + zval default_value; + if (zend_get_default_from_internal_arg_info(&default_value, (zend_arg_info *)arg_info) == FAILURE) { + /* Default value not available, so we can't pass any further defaults either. */ + return; + } + + if (Z_TYPE(default_value) == IS_CONSTANT_AST) { + zval_update_constant_ex(&default_value, fbc->common.scope); + } + + zend_vm_stack_extend_call_frame(call_ptr, num_passed_args, 1); + zval *arg = ZEND_CALL_VAR_NUM(*call_ptr, num_passed_args); + ZVAL_COPY_VALUE(arg, &default_value); + if (ARG_SHOULD_BE_SENT_BY_REF(fbc, num_passed_args + 1)) { + ZVAL_MAKE_REF(arg); + } + + num_passed_args++; + ZEND_CALL_NUM_ARGS(*call_ptr)++; + } +} +#endif + static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */ { int i; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 2d059159a23c..f1ff8f123524 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4108,6 +4108,9 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 38b869c4a4c0..463943f8c8c4 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1339,6 +1339,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; @@ -1405,6 +1408,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_D zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; @@ -1471,6 +1477,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; @@ -57139,6 +57148,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; @@ -57205,6 +57217,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_ICA zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data; @@ -57271,6 +57286,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_DO_IC zval retval; SAVE_OPLINE(); +#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS +zend_verify_internal_param_defaults(&call); +#endif EX(call) = call->prev_execute_data; call->prev_execute_data = execute_data;