From efdfba4fc48194af9496f5082bb1b24dc596f09b Mon Sep 17 00:00:00 2001 From: lacatoire Date: Tue, 18 Aug 2026 07:19:18 +0200 Subject: [PATCH 1/2] ext/intl: report argument #3 ($variant) for an invalid IDNA variant 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. --- ext/intl/idn/idn.cpp | 2 +- ext/intl/tests/idn_uts46_errors.phpt | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ext/intl/idn/idn.cpp b/ext/intl/idn/idn.cpp index 76cca2281296..811450c84e67 100644 --- a/ext/intl/idn/idn.cpp +++ b/ext/intl/idn/idn.cpp @@ -126,7 +126,7 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode) 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 c1058c3a2439..be7121482b7f 100644 --- a/ext/intl/tests/idn_uts46_errors.phpt +++ b/ext/intl/tests/idn_uts46_errors.phpt @@ -18,6 +18,13 @@ try { 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 @@ var_dump($foo["errors"]==IDNA_ERROR_CONTEXTJ); --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: From 6267d42edc3c6ebc22b0353b3aefacc377a44ae4 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Wed, 2 Sep 2026 11:06:37 +0200 Subject: [PATCH 2/2] ext/intl: fix the format specifier in the domain length error 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. --- ext/intl/idn/idn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/intl/idn/idn.cpp b/ext/intl/idn/idn.cpp index 811450c84e67..c1db9a84ccd0 100644 --- a/ext/intl/idn/idn.cpp +++ b/ext/intl/idn/idn.cpp @@ -122,7 +122,7 @@ 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) {