Commit e60d756f2cc for php.net

commit e60d756f2ccf5754b4acb656c39d35b74f423b8c
Author: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com>
Date:   Thu Jul 16 18:43:40 2026 +0200

    zend_API: Add `_ex` variants of `zend_argument_error*` (#21829)

    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.

diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 462e567f3f3..cca78d1d3b4 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -129,6 +129,9 @@ PHP 8.6 INTERNALS UPGRADE NOTES
     zend_reflection_property_set_raw_value() to expose the functionality of
     ReflectionProperty::setRawValueWithoutLazyInitialization() and
     ReflectionProperty::setRawValue() to C extensions.
+  . zend_argument_error_variadic() now takes a new 'function' parameters.
+  . Added zend_argument_error_ex(), zend_argument_type_error_ex(),
+    zend_argument_value_error_ex().

 ========================
 2. Build system changes
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index e334b18fe1a..72f4727eedd 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -374,7 +374,8 @@ 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(
+	zend_class_entry *error_ce, const zend_function *function, uint32_t arg_num, const char *format, va_list va)
 {
 	zend_string *func_name;
 	const char *arg_name;
@@ -383,8 +384,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,34 +395,65 @@ 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_argument_error_ex(zend_class_entry *error_ce, const zend_function *function, uint32_t arg_num, const char *format, ...)
+{
+	va_list va;
+
+	va_start(va, format);
+	zend_argument_error_variadic(error_ce, function, arg_num, 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(error_ce, function, arg_num, format, va);
 	va_end(va);
 }
 /* }}} */

+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(zend_ce_type_error, function, arg_num, 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(zend_ce_type_error, function, arg_num, format, va);
 	va_end(va);
 }
 /* }}} */

+ZEND_API ZEND_COLD void zend_argument_value_error_ex(
+	const zend_function *function, uint32_t arg_num, const char *format, ...)
+{
+	va_list va;
+
+	va_start(va, format);
+	zend_argument_error_variadic(zend_ce_value_error, function, arg_num, format, va);
+	va_end(va);
+}
+
 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(zend_ce_value_error, function, arg_num, format, va);
 	va_end(va);
 }
 /* }}} */
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index 593be26788d..bbfe6425774 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -1579,10 +1579,13 @@ 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(zend_class_entry *error_ce, const zend_function *function, uint32_t arg_num, 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(zend_class_entry *error_ce, const zend_function *function, uint32_t arg_num, 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_value_error_ex(const zend_function *function, 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);
 ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string *new_name, const zend_class_entry *old_ce);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index ec9a97eeb25..61f89435843 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -8921,9 +8921,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 34b2455ce43..bcf4df0c8e7 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index e11ad5c3428..fa91f232bcd 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -640,7 +640,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_ce_value_error, zend_active_function(), arg_num, format, va);
 	} else {
 		arg_name = get_active_function_arg_name(arg_num);
 		php_verror(NULL, arg_name, type, format, va);