Skip to content

Commit 43c18f3

Browse files
committed
Fix GH-18823: setlocale's 2nd and 3rd argument ignores strict_types
Closes GH-18828.
1 parent 058c034 commit 43c18f3

File tree

5 files changed

+76
-8
lines changed

5 files changed

+76
-8
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ PHP NEWS
250250
. Fixed bug GH-18062 (is_callable(func(...), callable_name: $name) for first
251251
class callables returns wrong name). (timwolla)
252252
. Added array_first() and array_last(). (nielsdos)
253+
. Fixed bug GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types).
254+
(nielsdos)
253255

254256
- Streams:
255257
. Fixed bug GH-16889 (stream_select() timeout useless for pipes on Windows).

ext/standard/string.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4926,37 +4926,52 @@ PHP_FUNCTION(setlocale)
49264926
{
49274927
zend_long cat;
49284928
zval *args = NULL;
4929-
int num_args;
4929+
uint32_t num_args;
4930+
ALLOCA_FLAG(use_heap);
49304931

49314932
ZEND_PARSE_PARAMETERS_START(2, -1)
49324933
Z_PARAM_LONG(cat)
49334934
Z_PARAM_VARIADIC('+', args, num_args)
49344935
ZEND_PARSE_PARAMETERS_END();
49354936

4937+
zend_string **strings = do_alloca(sizeof(zend_string *) * num_args, use_heap);
4938+
4939+
for (uint32_t i = 0; i < num_args; i++) {
4940+
if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && !zend_parse_arg_str(&args[i], &strings[i], false, i + 2))) {
4941+
zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]);
4942+
goto out;
4943+
}
4944+
}
4945+
49364946
for (uint32_t i = 0; i < num_args; i++) {
49374947
if (Z_TYPE(args[i]) == IS_ARRAY) {
49384948
zval *elem;
49394949
ZEND_HASH_FOREACH_VAL(Z_ARRVAL(args[i]), elem) {
49404950
zend_string *result = try_setlocale_zval(cat, elem);
49414951
if (EG(exception)) {
4942-
RETURN_THROWS();
4952+
goto out;
49434953
}
49444954
if (result) {
4945-
RETURN_STR(result);
4955+
RETVAL_STR(result);
4956+
goto out;
49464957
}
49474958
} ZEND_HASH_FOREACH_END();
49484959
} else {
4949-
zend_string *result = try_setlocale_zval(cat, &args[i]);
4960+
zend_string *result = try_setlocale_str(cat, strings[i]);
49504961
if (EG(exception)) {
4951-
RETURN_THROWS();
4962+
goto out;
49524963
}
49534964
if (result) {
4954-
RETURN_STR(result);
4965+
RETVAL_STR(result);
4966+
goto out;
49554967
}
49564968
}
49574969
}
49584970

4959-
RETURN_FALSE;
4971+
RETVAL_FALSE;
4972+
4973+
out:
4974+
free_alloca(strings, use_heap);
49604975
}
49614976
/* }}} */
49624977

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types) - strict mode
3+
--FILE--
4+
<?php
5+
declare(strict_types=1);
6+
try {
7+
setlocale(LC_ALL, 0, "0");
8+
} catch (TypeError $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
try {
12+
setlocale(LC_ALL, "0", 0);
13+
} catch (TypeError $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
?>
17+
--EXPECT--
18+
setlocale(): Argument #2 ($locales) must be of type array|string, int given
19+
setlocale(): Argument #3 must be of type array|string, int given
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-18823 (setlocale's 2nd and 3rd argument ignores strict_types) - weak mode
3+
--INI--
4+
error_reporting=E_ALL
5+
--FILE--
6+
<?php
7+
class MyStringable {
8+
public function __toString(): string {
9+
return 'foo';
10+
}
11+
}
12+
13+
class MyStringableThrow {
14+
public function __toString(): string {
15+
throw new Error('no');
16+
}
17+
}
18+
19+
setlocale(LC_ALL, 0, "0");
20+
setlocale(LC_ALL, "0", 0);
21+
setlocale(LC_ALL, null);
22+
setlocale(LC_ALL, new MyStringable);
23+
24+
try {
25+
setlocale(LC_ALL, new MyStringableThrow);
26+
} catch (Error $e) {
27+
echo $e->getMessage(), "\n";
28+
}
29+
?>
30+
--EXPECTF--
31+
Deprecated: setlocale(): Passing null to parameter #2 ($locales) of type string is deprecated in %s on line %d
32+
no

ext/standard/tests/strings/setlocale_variation4.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var_dump($locale_info_before);
2828

2929
//Testing setlocale() by giving locale = null
3030
echo "Setting system locale, category = LC_ALL and locale = null\n";
31-
setlocale(LC_ALL, null);
31+
@setlocale(LC_ALL, null);
3232

3333
echo "Locale info, after setting the locale\n";
3434
//Returns Current locale,after executing setlocale().

0 commit comments

Comments
 (0)