From cc545f3113b1806b69b7e1ec29aeb966590fa599 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sat, 20 Jun 2026 12:35:37 +0800 Subject: [PATCH 1/3] ext/standard: Reject NUL bytes in openlog() (#22366) When the value of the parameter of openlog() contains NUL byte(s), throw a ValueError instead of silently truncates it. --- NEWS | 2 ++ UPGRADING | 2 ++ ext/standard/syslog.c | 2 +- .../tests/network/openlog_null_bytes.phpt | 16 ++++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/network/openlog_null_bytes.phpt diff --git a/NEWS b/NEWS index 363c52506403..0842807e12ac 100644 --- a/NEWS +++ b/NEWS @@ -257,6 +257,8 @@ PHP NEWS contains null bytes. (Weilin Du) . dl() now raises a ValueError when the $extension_filename argument contains null bytes. (Weilin Du) + . openlog() now raises a ValueError when the $prefix argument contains + null bytes. (Weilin Du) . parse_str() now raises a ValueError when the $string argument contains null bytes. (Weilin Du) . proc_open() now raises a ValueError when the $cwd argument contains diff --git a/UPGRADING b/UPGRADING index a9b1f34eae5a..c77bfbfa4e02 100644 --- a/UPGRADING +++ b/UPGRADING @@ -153,6 +153,8 @@ PHP 8.6 UPGRADE NOTES contains null bytes. . dl() now raises a ValueError when the $extension_filename argument contains null bytes. + . openlog() now raises a ValueError when the $prefix argument contains + null bytes. . parse_str() now raises a ValueError when the $string argument contains null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. diff --git a/ext/standard/syslog.c b/ext/standard/syslog.c index 44b902bf50b8..78dfb2297fdc 100644 --- a/ext/standard/syslog.c +++ b/ext/standard/syslog.c @@ -61,7 +61,7 @@ PHP_FUNCTION(openlog) size_t ident_len; ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_STRING(ident, ident_len) + Z_PARAM_PATH(ident, ident_len) Z_PARAM_LONG(option) Z_PARAM_LONG(facility) ZEND_PARSE_PARAMETERS_END(); diff --git a/ext/standard/tests/network/openlog_null_bytes.phpt b/ext/standard/tests/network/openlog_null_bytes.phpt new file mode 100644 index 000000000000..6d3274227815 --- /dev/null +++ b/ext/standard/tests/network/openlog_null_bytes.phpt @@ -0,0 +1,16 @@ +--TEST-- +openlog() rejects null bytes in prefix +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} +?> +--EXPECT-- +openlog(): Argument #1 ($prefix) must not contain any null bytes From 4efca40953435efce4511e494d28c8496b51b712 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sat, 20 Jun 2026 13:07:19 +0800 Subject: [PATCH 2/3] ext/intl: Fix Locale::lookup() fallback on invalid language tags (#22306) Locale::lookup() and locale_lookup() should not return the fallback locale when canonicalizing a language tag fails. Returning the fallback hid the intl error raised by lookup_loc_range() for invalid language tags. Return NULL in that error case instead, while preserving the exception path when intl.use_exceptions is enabled. Closes #22306 --- NEWS | 2 ++ ext/intl/locale/locale_methods.c | 18 +++++++--- .../locale_lookup_invalid_language_tag.phpt | 35 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 ext/intl/tests/locale_lookup_invalid_language_tag.phpt diff --git a/NEWS b/NEWS index 32bb0b49f344..df93cb5b77b6 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,8 @@ PHP NEWS for invalid display types. (Weilin Du) . Fixed Spoofchecker restriction-level APIs to only be exposed with ICU 53 and later. (Graham Campbell) + . Fixed Locale::lookup() and locale_lookup() to return NULL instead of the + fallback locale when a language tag cannot be canonicalized. (Weilin Du) - mysqli: . Fix stmt->query leak in mysqli_execute_query() validation errors. diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c index e7cc9d8364c9..b5d48257338a 100644 --- a/ext/intl/locale/locale_methods.c +++ b/ext/intl/locale/locale_methods.c @@ -1435,14 +1435,15 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr, zend_argument_type_error(2, "must only contain string values"); LOOKUP_CLEAN_RETURN(NULL); } - cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value)); - result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[cur_arr_len*2]); + i = cur_arr_len*2; + cur_arr[i] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value)); + cur_arr_len++; + result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[i]); if(result == 0) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "lookup_loc_range: unable to canonicalize lang_tag", 0); LOOKUP_CLEAN_RETURN(NULL); } - cur_arr[cur_arr_len*2+1] = Z_STRVAL_P(ele_value); - cur_arr_len++ ; + cur_arr[i+1] = Z_STRVAL_P(ele_value); } ZEND_HASH_FOREACH_END(); /* end of for */ /* Canonicalize array elements */ @@ -1562,6 +1563,15 @@ PHP_FUNCTION(locale_lookup) } result_str = lookup_loc_range(loc_range, hash_arr, boolCanonical); + if (EG(exception)) { + RETURN_THROWS(); + } + if (U_FAILURE(intl_error_get_code(NULL))) { + if (result_str) { + zend_string_release_ex(result_str, 0); + } + RETURN_NULL(); + } if(result_str == NULL || ZSTR_VAL(result_str)[0] == '\0') { if( fallback_loc_str ) { result_str = zend_string_copy(fallback_loc_str); diff --git a/ext/intl/tests/locale_lookup_invalid_language_tag.phpt b/ext/intl/tests/locale_lookup_invalid_language_tag.phpt new file mode 100644 index 000000000000..6f7c7517f951 --- /dev/null +++ b/ext/intl/tests/locale_lookup_invalid_language_tag.phpt @@ -0,0 +1,35 @@ +--TEST-- +Locale::lookup() returns null for invalid language tags +--EXTENSIONS-- +intl +--FILE-- +getMessage(), PHP_EOL; +} + +try { + locale_lookup([''], 'de-DE', false, 'en-US'); +} catch (IntlException $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +NULL +string(75) "lookup_loc_range: unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" +NULL +string(75) "lookup_loc_range: unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" +lookup_loc_range: unable to canonicalize lang_tag +lookup_loc_range: unable to canonicalize lang_tag From cf18c77d6cce1eddaf6d1640cc9818277ab28087 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Sat, 20 Jun 2026 13:49:37 +0800 Subject: [PATCH 3/3] ext/intl: Fix Locale::lookup() test expectations (#22306) PHP 8.5 prefixes intl error messages with the calling function name. Update the regression test expectations to match the branch behavior for Locale::lookup() and locale_lookup(). --- ext/intl/tests/locale_lookup_invalid_language_tag.phpt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/intl/tests/locale_lookup_invalid_language_tag.phpt b/ext/intl/tests/locale_lookup_invalid_language_tag.phpt index ea4e3ec1cd0f..3ba48f61334b 100644 --- a/ext/intl/tests/locale_lookup_invalid_language_tag.phpt +++ b/ext/intl/tests/locale_lookup_invalid_language_tag.phpt @@ -28,8 +28,8 @@ try { ?> --EXPECT-- NULL -string(57) "unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" +string(75) "Locale::lookup(): unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" NULL -string(57) "unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" -unable to canonicalize lang_tag -unable to canonicalize lang_tag +string(74) "locale_lookup(): unable to canonicalize lang_tag: U_ILLEGAL_ARGUMENT_ERROR" +Locale::lookup(): unable to canonicalize lang_tag +locale_lookup(): unable to canonicalize lang_tag