Commit 2bbe62eb567 for php.net

commit 2bbe62eb5677e4612eac880a27a3c5a9cba73128
Author: Louis-Arnaud <la.catoire@gmail.com>
Date:   Wed Sep 2 11:59:45 2026 +0200

    ext/intl: report argument #3 ($variant) for an invalid IDNA variant (#23533)

    - php_intl_idn_handoff() takes domain, flags, variant, so the variant
    check must report argument 3; it hardcodes 2, which makes idn_to_ascii()
    and idn_to_utf8() blame $flags for a value carried by $variant.
    - The message concatenated PRId32 as a literal instead of using it as a
    conversion, so it read "must be less than d bytes" and INT32_MAX was
    never printed.

diff --git a/ext/intl/idn/idn.cpp b/ext/intl/idn/idn.cpp
index 76cca228129..c1db9a84ccd 100644
--- a/ext/intl/idn/idn.cpp
+++ b/ext/intl/idn/idn.cpp
@@ -122,11 +122,11 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
 		RETURN_THROWS();
 	}
 	if (UNEXPECTED(ZSTR_LEN(domain) > INT32_MAX - 1)) {
-		zend_argument_value_error(1, "must be less than " PRId32 " bytes", INT32_MAX);
+		zend_argument_value_error(1, "must be less than %" PRId32 " bytes", INT32_MAX);
 		RETURN_THROWS();
 	}
 	if (variant != INTL_IDN_VARIANT_UTS46) {
-		zend_argument_value_error(2, "must be INTL_IDNA_VARIANT_UTS46");
+		zend_argument_value_error(3, "must be INTL_IDNA_VARIANT_UTS46");
 		RETURN_THROWS();
 	}
 	/* don't check options; it wasn't checked before */
diff --git a/ext/intl/tests/idn_uts46_errors.phpt b/ext/intl/tests/idn_uts46_errors.phpt
index c1058c3a243..be7121482b7 100644
--- a/ext/intl/tests/idn_uts46_errors.phpt
+++ b/ext/intl/tests/idn_uts46_errors.phpt
@@ -18,6 +18,13 @@
     echo $e::class, ': ', $e->getMessage(), PHP_EOL;
 }

+echo "bad variant, named argument:", "\n";
+try {
+    var_dump(idn_to_utf8("xn--fuball-cta.com", variant: INTL_IDNA_VARIANT_UTS46 + 10));
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+}
+
 echo "empty domain:", "\n";
 try {
     var_dump(idn_to_ascii("", 0, INTL_IDNA_VARIANT_UTS46));
@@ -45,7 +52,9 @@
 --EXPECT--
 => PHP level errors
 bad variant:
-ValueError: idn_to_ascii(): Argument #2 ($flags) must be INTL_IDNA_VARIANT_UTS46
+ValueError: idn_to_ascii(): Argument #3 ($variant) must be INTL_IDNA_VARIANT_UTS46
+bad variant, named argument:
+ValueError: idn_to_utf8(): Argument #3 ($variant) must be INTL_IDNA_VARIANT_UTS46
 empty domain:
 ValueError: idn_to_ascii(): Argument #1 ($domain) must not be empty
 with error, but no details arg: