Skip to content

Commit 404fb15

Browse files
committed
Add mode for verifying internal function params
1 parent 4aa137c commit 404fb15

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
@@ -4268,6 +4268,44 @@ static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant(
42684268
return _zend_quick_get_constant(key, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
42694269
} /* }}} */
42704270

4271+
/* Replace optional parameters that weren't passed with their declared default values,
4272+
* which allows us to check that this does not change the behavior of the function. */
4273+
#define ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS 1
4274+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
4275+
static void zend_verify_internal_param_defaults(zend_execute_data **call_ptr) {
4276+
zend_function *fbc = (*call_ptr)->func;
4277+
uint32_t num_passed_args = ZEND_CALL_NUM_ARGS(*call_ptr);
4278+
if (num_passed_args < fbc->common.required_num_args) {
4279+
/* This is an error anyway. */
4280+
return;
4281+
}
4282+
4283+
uint32_t num_declared_args = fbc->common.num_args;
4284+
while (num_passed_args < num_declared_args) {
4285+
zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[num_passed_args];
4286+
zval default_value;
4287+
if (zend_get_default_from_internal_arg_info(&default_value, arg_info) == FAILURE) {
4288+
/* Default value not available, so we can't pass any further defaults either. */
4289+
return;
4290+
}
4291+
4292+
if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
4293+
zval_update_constant_ex(&default_value, fbc->common.scope);
4294+
}
4295+
4296+
zend_vm_stack_extend_call_frame(call_ptr, num_passed_args, 1);
4297+
zval *arg = ZEND_CALL_VAR_NUM(*call_ptr, num_passed_args);
4298+
ZVAL_COPY_VALUE(arg, &default_value);
4299+
if (ARG_SHOULD_BE_SENT_BY_REF(fbc, num_passed_args + 1)) {
4300+
ZVAL_MAKE_REF(arg);
4301+
}
4302+
4303+
num_passed_args++;
4304+
ZEND_CALL_NUM_ARGS(*call_ptr)++;
4305+
}
4306+
}
4307+
#endif
4308+
42714309
#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
42724310
/* Special versions of functions that sets EX(opline) before calling zend_vm_stack_extend() */
42734311
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
@@ -3858,8 +3858,11 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
38583858
zval retval;
38593859

38603860
SAVE_OPLINE();
3861-
EX(call) = call->prev_execute_data;
3861+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
3862+
zend_verify_internal_param_defaults(&call);
3863+
#endif
38623864

3865+
EX(call) = call->prev_execute_data;
38633866
call->prev_execute_data = execute_data;
38643867
EG(current_execute_data) = call;
38653868

Zend/zend_vm_execute.h

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

12231223
SAVE_OPLINE();
1224-
EX(call) = call->prev_execute_data;
1224+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
1225+
zend_verify_internal_param_defaults(&call);
1226+
#endif
12251227

1228+
EX(call) = call->prev_execute_data;
12261229
call->prev_execute_data = execute_data;
12271230
EG(current_execute_data) = call;
12281231

@@ -1273,8 +1276,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV
12731276
zval retval;
12741277

12751278
SAVE_OPLINE();
1276-
EX(call) = call->prev_execute_data;
1279+
#if ZEND_VERIFY_INTERNAL_PARAM_DEFAULTS
1280+
zend_verify_internal_param_defaults(&call);
1281+
#endif
12771282

1283+
EX(call) = call->prev_execute_data;
12781284
call->prev_execute_data = execute_data;
12791285
EG(current_execute_data) = call;
12801286

0 commit comments

Comments
 (0)