From add4d021e66c6e6521e32a1511c20b3a43d760f4 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 22 Apr 2026 10:36:35 +0200 Subject: [PATCH 1/2] Add zend_argument_type_error_ex, zend_argument_error_ex These variants take the function as parameter instead of infering it from the call stack. This is useful in ZEND_TYPE_ASSERT, and will be used in PFA impl. --- Zend/zend_API.c | 39 ++++++++++++++++++++++++++++++++++++--- Zend/zend_API.h | 8 ++++++++ Zend/zend_vm_def.h | 5 +++-- Zend/zend_vm_execute.h | 10 ++++++---- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index ccb770a9963b..0b58fbed2c10 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -374,7 +374,9 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void) ); } -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic_ex( + const zend_function *function, uint32_t arg_num, + zend_class_entry *error_ce, const char *format, va_list va) { zend_string *func_name; const char *arg_name; @@ -383,8 +385,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_en return; } - func_name = get_active_function_or_method_name(); - arg_name = get_active_function_arg_name(arg_num); + func_name = get_function_or_method_name(function); + arg_name = get_function_arg_name(function, arg_num); zend_vspprintf(&message, 0, format, va); zend_throw_error(error_ce, "%s(): Argument #%d%s%s%s %s", @@ -394,8 +396,27 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_en efree(message); zend_string_release(func_name); } + +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */ +{ + ZEND_ASSERT(zend_is_executing()); + + const zend_function *function = zend_active_function(); + + zend_argument_error_variadic_ex(function, arg_num, error_ce, format, va); +} /* }}} */ +ZEND_API ZEND_COLD void zend_argument_error_ex(const zend_function *function, + uint32_t arg_num, zend_class_entry *error_ce, const char *format, ...) +{ + va_list va; + + va_start(va, format); + zend_argument_error_variadic_ex(function, arg_num, error_ce, format, va); + va_end(va); +} + ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */ { va_list va; @@ -406,6 +427,18 @@ ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t } /* }}} */ +ZEND_API ZEND_COLD void zend_argument_type_error_ex( + const zend_function *function, uint32_t arg_num, + const char *format, ...) +{ + va_list va; + + va_start(va, format); + zend_argument_error_variadic_ex(function, arg_num, + zend_ce_type_error, format, va); + va_end(va); +} + ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */ { va_list va; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 01a9202be1c3..4016b69da401 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1565,8 +1565,16 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, ch ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic_ex( + const zend_function *function, uint32_t arg_num, + zend_class_entry *error_ce, const char *format, va_list va); ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...); +ZEND_API ZEND_COLD void zend_argument_error_ex(const zend_function *function, + uint32_t arg_num, zend_class_entry *error_ce, const char *format, ...); ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...); +ZEND_API ZEND_COLD void zend_argument_type_error_ex( + const zend_function *function, uint32_t arg_num, + const char *format, ...); ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...); ZEND_API ZEND_COLD void zend_argument_must_not_be_empty_error(uint32_t arg_num); ZEND_API ZEND_COLD void zend_class_redeclaration_error(int type, const zend_class_entry *old_ce); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 05923bbc2b61..c88c3ea5a81d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8918,9 +8918,10 @@ ZEND_VM_HOT_HANDLER(211, ZEND_TYPE_ASSERT, CONST, ANY, NUM) zend_arg_info *arginfo = &fbc->common.arg_info[argno - 1]; if (!zend_check_type(&arginfo->type, value, /* is_return_type */ false, /* is_internal */ true)) { - const char *param_name = get_function_arg_name(fbc, argno); zend_string *expected = zend_type_to_string(arginfo->type); - zend_type_error("%s(): Argument #%d%s%s%s must be of type %s, %s given", ZSTR_VAL(fbc->common.function_name), argno, param_name ? " ($" : "", param_name ? param_name : "", param_name ? ")" : "", ZSTR_VAL(expected), zend_zval_value_name(value)); + zend_argument_type_error_ex(fbc, argno, + "must be of type %s, %s given", + ZSTR_VAL(expected), zend_zval_value_name(value)); zend_string_release(expected); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2b5b9e5fcd47..33cc3de9b498 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -6160,9 +6160,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_T zend_arg_info *arginfo = &fbc->common.arg_info[argno - 1]; if (!zend_check_type(&arginfo->type, value, /* is_return_type */ false, /* is_internal */ true)) { - const char *param_name = get_function_arg_name(fbc, argno); zend_string *expected = zend_type_to_string(arginfo->type); - zend_type_error("%s(): Argument #%d%s%s%s must be of type %s, %s given", ZSTR_VAL(fbc->common.function_name), argno, param_name ? " ($" : "", param_name ? param_name : "", param_name ? ")" : "", ZSTR_VAL(expected), zend_zval_value_name(value)); + zend_argument_type_error_ex(fbc, argno, + "must be of type %s, %s given", + ZSTR_VAL(expected), zend_zval_value_name(value)); zend_string_release(expected); } } @@ -58818,9 +58819,10 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_TYPE_A zend_arg_info *arginfo = &fbc->common.arg_info[argno - 1]; if (!zend_check_type(&arginfo->type, value, /* is_return_type */ false, /* is_internal */ true)) { - const char *param_name = get_function_arg_name(fbc, argno); zend_string *expected = zend_type_to_string(arginfo->type); - zend_type_error("%s(): Argument #%d%s%s%s must be of type %s, %s given", ZSTR_VAL(fbc->common.function_name), argno, param_name ? " ($" : "", param_name ? param_name : "", param_name ? ")" : "", ZSTR_VAL(expected), zend_zval_value_name(value)); + zend_argument_type_error_ex(fbc, argno, + "must be of type %s, %s given", + ZSTR_VAL(expected), zend_zval_value_name(value)); zend_string_release(expected); } } From 2fd627d1bd301875f86267545c3404f6c69b83e6 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 6 May 2026 11:27:30 +0200 Subject: [PATCH 2/2] Reduce API surface --- Zend/zend_API.c | 26 +++++++++----------------- Zend/zend_API.h | 3 +-- ext/openssl/openssl.c | 2 +- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 0b58fbed2c10..8429c9237d80 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -374,7 +374,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void) ); } -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic_ex( +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic( const zend_function *function, uint32_t arg_num, zend_class_entry *error_ce, const char *format, va_list va) { @@ -397,32 +397,23 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic_ex( zend_string_release(func_name); } -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */ -{ - ZEND_ASSERT(zend_is_executing()); - - const zend_function *function = zend_active_function(); - - zend_argument_error_variadic_ex(function, arg_num, error_ce, format, va); -} -/* }}} */ - ZEND_API ZEND_COLD void zend_argument_error_ex(const zend_function *function, uint32_t arg_num, zend_class_entry *error_ce, const char *format, ...) { va_list va; va_start(va, format); - zend_argument_error_variadic_ex(function, arg_num, error_ce, format, va); + zend_argument_error_variadic(function, arg_num, error_ce, format, va); va_end(va); } ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */ { va_list va; + const zend_function *function = zend_active_function(); va_start(va, format); - zend_argument_error_variadic(error_ce, arg_num, format, va); + zend_argument_error_variadic(function, arg_num, error_ce, format, va); va_end(va); } /* }}} */ @@ -434,17 +425,17 @@ ZEND_API ZEND_COLD void zend_argument_type_error_ex( va_list va; va_start(va, format); - zend_argument_error_variadic_ex(function, arg_num, - zend_ce_type_error, format, va); + zend_argument_error_variadic(function, arg_num, zend_ce_type_error, format, va); va_end(va); } ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */ { va_list va; + const zend_function *function = zend_active_function(); va_start(va, format); - zend_argument_error_variadic(zend_ce_type_error, arg_num, format, va); + zend_argument_error_variadic(function, arg_num, zend_ce_type_error, format, va); va_end(va); } /* }}} */ @@ -452,9 +443,10 @@ ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *f ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...) /* {{{ */ { va_list va; + const zend_function *function = zend_active_function(); va_start(va, format); - zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va); + zend_argument_error_variadic(function, arg_num, zend_ce_value_error, format, va); va_end(va); } /* }}} */ diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 4016b69da401..b34f37d8079e 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1564,8 +1564,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_nu ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va); -ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic_ex( +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic( const zend_function *function, uint32_t arg_num, zend_class_entry *error_ce, const char *format, va_list va); ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...); diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index c85ca073f446..570dc03f9f91 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -566,7 +566,7 @@ static void php_openssl_check_path_error(uint32_t arg_num, int type, const char va_start(va, format); if (type == E_ERROR) { - zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va); + zend_argument_error_variadic(zend_active_function(), arg_num, zend_ce_value_error, format, va); } else { arg_name = get_active_function_arg_name(arg_num); php_verror(NULL, arg_name, type, format, va);