From a6e63b42c3ba1e45fc4c2e2154ca34e844f323b1 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 31 Jul 2020 12:00:56 +0200 Subject: [PATCH] Make check in RECV_VARIADIC more precise Fetch arg_info only once (it's always the same one...) and check ZEND_TYPE_IS_SET on it, rather than checking if *any* parameter has a type. --- Zend/zend_execute.c | 15 +++++---------- Zend/zend_vm_def.h | 10 ++++++---- Zend/zend_vm_execute.h | 10 ++++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 51d4a0d003..d6809cb670 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1051,17 +1051,12 @@ static zend_always_inline int zend_verify_recv_arg_type(zend_function *zf, uint3 return 1; } -static zend_always_inline int zend_verify_variadic_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot) +static zend_always_inline int zend_verify_variadic_arg_type( + zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot) { - zend_arg_info *cur_arg_info; - - ZEND_ASSERT(arg_num > zf->common.num_args); - ZEND_ASSERT(zf->common.fn_flags & ZEND_ACC_VARIADIC); - cur_arg_info = &zf->common.arg_info[zf->common.num_args]; - - if (ZEND_TYPE_IS_SET(cur_arg_info->type) - && UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { - zend_verify_arg_error(zf, cur_arg_info, arg_num, cache_slot, arg); + ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type)); + if (UNEXPECTED(!zend_check_type(arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) { + zend_verify_arg_error(zf, arg_info, arg_num, cache_slot, arg); return 0; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e69075bd88..a9b5c0f4a3 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5170,15 +5170,17 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT) params = EX_VAR(opline->result.var); if (arg_num <= arg_count) { - zval *param; + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC); + ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1); + zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1]; array_init_size(params, arg_count - arg_num + 1); zend_hash_real_init_packed(Z_ARRVAL_P(params)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { - param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (UNEXPECTED(ZEND_TYPE_IS_SET(arg_info->type))) { do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { ZEND_HASH_FILL_FINISH(); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d265a266f2..3e6edeb8df 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3120,15 +3120,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_UNUSED_HAND params = EX_VAR(opline->result.var); if (arg_num <= arg_count) { - zval *param; + ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC); + ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1); + zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1]; array_init_size(params, arg_count - arg_num + 1); zend_hash_real_init_packed(Z_ARRVAL_P(params)); ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) { - param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) { + zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T); + if (UNEXPECTED(ZEND_TYPE_IS_SET(arg_info->type))) { do { - if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) { + if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) { ZEND_HASH_FILL_FINISH(); HANDLE_EXCEPTION(); } -- 2.50.1