From 017bcaca92fa25a26ed4678a162870ae73f56b1e Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 10 Jun 2025 20:14:49 +0200 Subject: [PATCH 1/4] Fix GH-18823: setlocale's 2nd and 3rd argument ignores strict_types --- ext/standard/string.c | 9 +++++++++ ext/standard/tests/strings/gh18823.phpt | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 ext/standard/tests/strings/gh18823.phpt diff --git a/ext/standard/string.c b/ext/standard/string.c index f21c9be8a7bd2..07d1cf62e9e89 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4933,6 +4933,15 @@ PHP_FUNCTION(setlocale) Z_PARAM_VARIADIC('+', args, num_args) ZEND_PARSE_PARAMETERS_END(); + if (ZEND_ARG_USES_STRICT_TYPES()) { + for (uint32_t i = 0; i < num_args; i++) { + if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && Z_TYPE(args[i]) != IS_STRING)) { + zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]); + RETURN_THROWS(); + } + } + } + for (uint32_t i = 0; i < num_args; i++) { if (Z_TYPE(args[i]) == IS_ARRAY) { zval *elem; diff --git a/ext/standard/tests/strings/gh18823.phpt b/ext/standard/tests/strings/gh18823.phpt new file mode 100644 index 0000000000000..46355942a2340 --- /dev/null +++ b/ext/standard/tests/strings/gh18823.phpt @@ -0,0 +1,19 @@ +--TEST-- +GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types) +--FILE-- +getMessage(), "\n"; +} +try { + setlocale(LC_ALL, "0", 0); +} catch (TypeError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +setlocale(): Argument #2 ($locales) must be of type array|string, int given +setlocale(): Argument #3 must be of type array|string, int given From 2370a04a1707a3ec0c8c5767c999f28ba3feac63 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Tue, 10 Jun 2025 21:10:23 +0200 Subject: [PATCH 2/4] Fix type --- ext/standard/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 07d1cf62e9e89..d28adc68851af 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4926,7 +4926,7 @@ PHP_FUNCTION(setlocale) { zend_long cat; zval *args = NULL; - int num_args; + uint32_t num_args; ZEND_PARSE_PARAMETERS_START(2, -1) Z_PARAM_LONG(cat) From 862ee53a01559f4e3f880ef03f12601a9fd42a26 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Jun 2025 20:03:01 +0200 Subject: [PATCH 3/4] address review comments --- ext/standard/string.c | 30 ++++++++++------- .../{gh18823.phpt => gh18823_strict.phpt} | 2 +- ext/standard/tests/strings/gh18823_weak.phpt | 32 +++++++++++++++++++ 3 files changed, 51 insertions(+), 13 deletions(-) rename ext/standard/tests/strings/{gh18823.phpt => gh18823_strict.phpt} (96%) create mode 100644 ext/standard/tests/strings/gh18823_weak.phpt diff --git a/ext/standard/string.c b/ext/standard/string.c index d28adc68851af..36903b3c5c7b9 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -4927,18 +4927,19 @@ PHP_FUNCTION(setlocale) zend_long cat; zval *args = NULL; uint32_t num_args; + ALLOCA_FLAG(use_heap); ZEND_PARSE_PARAMETERS_START(2, -1) Z_PARAM_LONG(cat) Z_PARAM_VARIADIC('+', args, num_args) ZEND_PARSE_PARAMETERS_END(); - if (ZEND_ARG_USES_STRICT_TYPES()) { - for (uint32_t i = 0; i < num_args; i++) { - if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && Z_TYPE(args[i]) != IS_STRING)) { - zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]); - RETURN_THROWS(); - } + zend_string **strings = do_alloca(sizeof(zend_string *) * num_args, use_heap); + + for (uint32_t i = 0; i < num_args; i++) { + if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && !zend_parse_arg_str(&args[i], &strings[i], false, i + 2))) { + zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]); + goto out; } } @@ -4948,24 +4949,29 @@ PHP_FUNCTION(setlocale) ZEND_HASH_FOREACH_VAL(Z_ARRVAL(args[i]), elem) { zend_string *result = try_setlocale_zval(cat, elem); if (EG(exception)) { - RETURN_THROWS(); + goto out; } if (result) { - RETURN_STR(result); + RETVAL_STR(result); + goto out; } } ZEND_HASH_FOREACH_END(); } else { - zend_string *result = try_setlocale_zval(cat, &args[i]); + zend_string *result = try_setlocale_str(cat, strings[i]); if (EG(exception)) { - RETURN_THROWS(); + goto out; } if (result) { - RETURN_STR(result); + RETVAL_STR(result); + goto out; } } } - RETURN_FALSE; + RETVAL_FALSE; + +out: + free_alloca(strings, use_heap); } /* }}} */ diff --git a/ext/standard/tests/strings/gh18823.phpt b/ext/standard/tests/strings/gh18823_strict.phpt similarity index 96% rename from ext/standard/tests/strings/gh18823.phpt rename to ext/standard/tests/strings/gh18823_strict.phpt index 46355942a2340..80b21d2093172 100644 --- a/ext/standard/tests/strings/gh18823.phpt +++ b/ext/standard/tests/strings/gh18823_strict.phpt @@ -1,5 +1,5 @@ --TEST-- -GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types) +GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types) - strict mode --FILE-- getMessage(), "\n"; +} +?> +--EXPECTF-- +Deprecated: setlocale(): Passing null to parameter #2 ($locales) of type string is deprecated in %s on line %d +no From 350e101b2712823e260a357c5074b88941bef65c Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 12 Jun 2025 21:07:37 +0200 Subject: [PATCH 4/4] Silence deprecation --- ext/standard/tests/strings/setlocale_variation4.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/tests/strings/setlocale_variation4.phpt b/ext/standard/tests/strings/setlocale_variation4.phpt index ca469759dbd15..a2b236c146c8c 100644 --- a/ext/standard/tests/strings/setlocale_variation4.phpt +++ b/ext/standard/tests/strings/setlocale_variation4.phpt @@ -28,7 +28,7 @@ var_dump($locale_info_before); //Testing setlocale() by giving locale = null echo "Setting system locale, category = LC_ALL and locale = null\n"; -setlocale(LC_ALL, null); +@setlocale(LC_ALL, null); echo "Locale info, after setting the locale\n"; //Returns Current locale,after executing setlocale().