Skip to content

Commit 5189450

Browse files
authored
ext/intl: Locale::* methods using param as path whenever relevant. (#18365)
close GH-18365
1 parent 6adbe84 commit 5189450

12 files changed

+142
-12
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ PHP NEWS
8888
(BogdanUngureanu)
8989
. Added Locale::isRightToLeft to check if a locale is written right to left.
9090
(David Carlier)
91+
. Added null bytes presence in locale inputs for Locale class. (David Carlier)
9192

9293
- MySQLi:
9394
. Fixed bugs GH-17900 and GH-8084 (calling mysqli::__construct twice).

UPGRADING

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ PHP 8.5 UPGRADE NOTES
212212
. grapheme_extract() properly assigns $next value when skipping over
213213
invalid starting bytes. Previously there were cases where it would
214214
point to the start of the grapheme boundary instead of the end.
215+
. Locale:: methods throw a ValueError when locale inputs contain null
216+
bytes.
215217

216218
- PCNTL:
217219
. pcntl_exec() now has a formal return type of false.

ext/intl/locale/locale_methods.c

+16-12
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ PHP_NAMED_FUNCTION(zif_locale_set_default)
315315
char *default_locale = NULL;
316316

317317
ZEND_PARSE_PARAMETERS_START(1, 1)
318-
Z_PARAM_STR(locale_name)
318+
Z_PARAM_PATH_STR(locale_name)
319319
ZEND_PARSE_PARAMETERS_END();
320320

321321
if (ZSTR_LEN(locale_name) == 0) {
@@ -481,7 +481,7 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS)
481481
intl_error_reset( NULL );
482482

483483
ZEND_PARSE_PARAMETERS_START(1, 1)
484-
Z_PARAM_STRING(loc_name, loc_name_len)
484+
Z_PARAM_PATH(loc_name, loc_name_len)
485485
ZEND_PARSE_PARAMETERS_END();
486486

487487
if(loc_name_len == 0) {
@@ -568,9 +568,9 @@ static void get_icu_disp_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAME
568568
intl_error_reset( NULL );
569569

570570
ZEND_PARSE_PARAMETERS_START(1, 2)
571-
Z_PARAM_STRING(loc_name, loc_name_len)
571+
Z_PARAM_PATH(loc_name, loc_name_len)
572572
Z_PARAM_OPTIONAL
573-
Z_PARAM_STRING_OR_NULL(disp_loc_name, disp_loc_name_len)
573+
Z_PARAM_PATH_OR_NULL(disp_loc_name, disp_loc_name_len)
574574
ZEND_PARSE_PARAMETERS_END();
575575

576576
if(loc_name_len > ULOC_FULLNAME_CAPACITY) {
@@ -735,7 +735,7 @@ PHP_FUNCTION( locale_get_keywords )
735735
intl_error_reset( NULL );
736736

737737
ZEND_PARSE_PARAMETERS_START(1, 1)
738-
Z_PARAM_STRING(loc_name, loc_name_len)
738+
Z_PARAM_PATH(loc_name, loc_name_len)
739739
ZEND_PARSE_PARAMETERS_END();
740740

741741
INTL_CHECK_LOCALE_LEN(strlen(loc_name));
@@ -1126,7 +1126,7 @@ PHP_FUNCTION(locale_parse)
11261126
intl_error_reset( NULL );
11271127

11281128
ZEND_PARSE_PARAMETERS_START(1, 1)
1129-
Z_PARAM_STRING(loc_name, loc_name_len)
1129+
Z_PARAM_PATH(loc_name, loc_name_len)
11301130
ZEND_PARSE_PARAMETERS_END();
11311131

11321132
INTL_CHECK_LOCALE_LEN(strlen(loc_name));
@@ -1166,7 +1166,7 @@ PHP_FUNCTION(locale_get_all_variants)
11661166
intl_error_reset( NULL );
11671167

11681168
ZEND_PARSE_PARAMETERS_START(1, 1)
1169-
Z_PARAM_STRING(loc_name, loc_name_len)
1169+
Z_PARAM_PATH(loc_name, loc_name_len)
11701170
ZEND_PARSE_PARAMETERS_END();
11711171

11721172
if(loc_name_len == 0) {
@@ -1260,8 +1260,8 @@ PHP_FUNCTION(locale_filter_matches)
12601260
intl_error_reset( NULL );
12611261

12621262
ZEND_PARSE_PARAMETERS_START(2, 3)
1263-
Z_PARAM_STRING(lang_tag, lang_tag_len)
1264-
Z_PARAM_STRING(loc_range, loc_range_len)
1263+
Z_PARAM_PATH(lang_tag, lang_tag_len)
1264+
Z_PARAM_PATH(loc_range, loc_range_len)
12651265
Z_PARAM_OPTIONAL
12661266
Z_PARAM_BOOL(boolCanonical)
12671267
ZEND_PARSE_PARAMETERS_END();
@@ -1434,6 +1434,10 @@ static zend_string* lookup_loc_range(const char* loc_range, HashTable* hash_arr,
14341434
zend_argument_type_error(2, "must only contain string values");
14351435
LOOKUP_CLEAN_RETURN(NULL);
14361436
}
1437+
if (zend_str_has_nul_byte(Z_STR_P(ele_value))) {
1438+
zend_argument_value_error(2, "must not contain any null bytes");
1439+
LOOKUP_CLEAN_RETURN(NULL);
1440+
}
14371441
cur_arr[cur_arr_len*2] = estrndup(Z_STRVAL_P(ele_value), Z_STRLEN_P(ele_value));
14381442
result = strToMatch(Z_STRVAL_P(ele_value), cur_arr[cur_arr_len*2]);
14391443
if(result == 0) {
@@ -1535,10 +1539,10 @@ PHP_FUNCTION(locale_lookup)
15351539

15361540
ZEND_PARSE_PARAMETERS_START(2, 4)
15371541
Z_PARAM_ARRAY(arr)
1538-
Z_PARAM_STRING(loc_range, loc_range_len)
1542+
Z_PARAM_PATH(loc_range, loc_range_len)
15391543
Z_PARAM_OPTIONAL
15401544
Z_PARAM_BOOL(boolCanonical)
1541-
Z_PARAM_STR_OR_NULL(fallback_loc_str)
1545+
Z_PARAM_PATH_STR_OR_NULL(fallback_loc_str)
15421546
ZEND_PARSE_PARAMETERS_END();
15431547

15441548
if(loc_range_len == 0) {
@@ -1626,7 +1630,7 @@ PHP_FUNCTION(locale_is_right_to_left)
16261630
size_t locale_len;
16271631

16281632
ZEND_PARSE_PARAMETERS_START(1, 1)
1629-
Z_PARAM_STRING(locale, locale_len)
1633+
Z_PARAM_PATH(locale, locale_len)
16301634
ZEND_PARSE_PARAMETERS_END();
16311635

16321636
if (!locale_len) {

ext/intl/tests/locale_filter_matches_icu70.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ function ut_main()
6969
}
7070
}
7171

72+
try {
73+
ut_loc_locale_filter_matches("de\0-DE", "de-DE", false);
74+
} catch (\ValueError $e) {
75+
echo $e->getMessage(). PHP_EOL;
76+
}
77+
78+
try {
79+
ut_loc_locale_filter_matches("de-DE", "d\0e-DE", false);
80+
} catch (\ValueError $e) {
81+
echo $e->getMessage(). PHP_EOL;
82+
}
83+
7284
$res_str .= "\n";
7385
return $res_str;
7486

@@ -79,6 +91,10 @@ ut_run();
7991

8092
?>
8193
--EXPECT--
94+
Locale::filterMatches(): Argument #1 ($languageTag) must not contain any null bytes
95+
Locale::filterMatches(): Argument #2 ($locale) must not contain any null bytes
96+
locale_filter_matches(): Argument #1 ($languageTag) must not contain any null bytes
97+
locale_filter_matches(): Argument #2 ($locale) must not contain any null bytes
8298
--------------
8399
loc_range:de-de matches lang_tag de-DEVA ? NO
84100
loc_range:de_DE canonically matches lang_tag de_Deva ? NO

ext/intl/tests/locale_get_all_variants.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ function ut_main()
3939
$res_str .= "\n";
4040
}
4141

42+
try {
43+
ut_loc_locale_get_all_variants("i-\0tay");
44+
} catch (\ValueError $e) {
45+
echo $e->getMessage(). PHP_EOL;
46+
}
47+
4248
$res_str .= "\n";
4349
return $res_str;
4450

@@ -49,6 +55,8 @@ ut_run();
4955

5056
?>
5157
--EXPECT--
58+
Locale::getAllVariants(): Argument #1 ($locale) must not contain any null bytes
59+
locale_get_all_variants(): Argument #1 ($locale) must not contain any null bytes
5260
sl_IT_nedis_KIRTI : variants 'NEDIS','KIRTI',
5361
sl_IT_nedis-a-kirti-x-xyz : variants 'NEDIS',
5462
sl_IT_rozaj : variants 'ROZAJ',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
locale_get_display_language() throwing null bytes exceptions.
3+
--EXTENSIONS--
4+
intl
5+
--FILE--
6+
<?php
7+
8+
function ut_main()
9+
{
10+
try {
11+
ut_loc_get_display_language("a-D\0E", "locale=a-DE");
12+
} catch (\ValueError $e) {
13+
echo $e->getMessage(). PHP_EOL;
14+
}
15+
16+
try {
17+
ut_loc_get_display_language("a-DE", "locale=a\0-DE");
18+
} catch (\ValueError $e) {
19+
echo $e->getMessage(). PHP_EOL;
20+
}
21+
}
22+
include_once 'ut_common.inc';
23+
ut_run();
24+
?>
25+
--EXPECT--
26+
Locale::getDisplayLanguage(): Argument #1 ($locale) must not contain any null bytes
27+
Locale::getDisplayLanguage(): Argument #2 ($displayLocale) must not contain any null bytes
28+
locale_get_display_language(): Argument #1 ($locale) must not contain any null bytes
29+
locale_get_display_language(): Argument #2 ($displayLocale) must not contain any null bytes

ext/intl/tests/locale_get_display_script4.phpt

+16
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ function ut_main()
8383
$res_str .= "-----------------\n";
8484
}
8585

86+
try {
87+
ut_loc_get_display_script("a-D\0E", "locale=a-DE");
88+
} catch (\ValueError $e) {
89+
echo $e->getMessage(). PHP_EOL;
90+
}
91+
92+
try {
93+
ut_loc_get_display_script("a-DE", "locale=a\0-DE");
94+
} catch (\ValueError $e) {
95+
echo $e->getMessage(). PHP_EOL;
96+
}
97+
8698
return $res_str;
8799

88100
}
@@ -92,6 +104,10 @@ ut_run();
92104

93105
?>
94106
--EXPECT--
107+
Locale::getDisplayScript(): Argument #1 ($locale) must not contain any null bytes
108+
Locale::getDisplayScript(): Argument #2 ($displayLocale) must not contain any null bytes
109+
locale_get_display_script(): Argument #1 ($locale) must not contain any null bytes
110+
locale_get_display_script(): Argument #2 ($displayLocale) must not contain any null bytes
95111
locale='uk-ua_CALIFORNIA@currency=;currency=GRN'
96112
disp_locale=en : display_script=
97113
disp_locale=fr : display_script=

ext/intl/tests/locale_get_region.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ function ut_main()
7676
$res_str .= "\n";
7777
}
7878

79+
try {
80+
ut_loc_get_region("a-\0DE");
81+
} catch (\ValueError $e) {
82+
echo $e->getMessage(). PHP_EOL;
83+
}
84+
7985
return $res_str;
8086

8187
}
@@ -85,6 +91,8 @@ ut_run();
8591

8692
?>
8793
--EXPECTF--
94+
Locale::getRegion(): Argument #1 ($locale) must not contain any null bytes
95+
locale_get_region(): Argument #1 ($locale) must not contain any null bytes
8896
uk-ua_CALIFORNIA@currency=;currency=GRN: region='UA'
8997
root: region=''
9098
uk@currency=EURO: region=''

ext/intl/tests/locale_get_script.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ function ut_main()
7474
$res_str .= "\n";
7575
}
7676

77+
try {
78+
ut_loc_get_script("de\0-419-DE");
79+
} catch (\ValueError $e) {
80+
echo $e->getMessage(). PHP_EOL;
81+
}
82+
7783
return $res_str;
7884

7985
}
@@ -83,6 +89,8 @@ ut_run();
8389

8490
?>
8591
--EXPECT--
92+
Locale::getScript(): Argument #1 ($locale) must not contain any null bytes
93+
locale_get_script(): Argument #1 ($locale) must not contain any null bytes
8694
uk-ua_CALIFORNIA@currency=;currency=GRN: script=''
8795
root: script=''
8896
uk@currency=EURO: script=''

ext/intl/tests/locale_is_right_to_left.phpt

+6
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ var_dump(Locale::isRightToLeft("en-US"));
88
var_dump(Locale::isRightToLeft("\INVALID\\"));
99
var_dump(Locale::isRightToLeft(""));
1010
var_dump(Locale::isRightToLeft("ar"));
11+
try {
12+
Locale::isRightToLeft("a\0r");
13+
} catch (\ValueError $e) {
14+
echo $e->getMessage();
15+
}
1116
?>
1217
--EXPECT--
1318
bool(false)
1419
bool(false)
1520
bool(false)
1621
bool(true)
22+
Locale::isRightToLeft(): Argument #1 ($locale) must not contain any null bytes

ext/intl/tests/locale_lookup_variant3.phpt

+24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,24 @@ function ut_main()
5959

6060
}
6161

62+
try {
63+
ut_loc_locale_lookup(["de\0-DE"], "de-DE", false, "en-US");
64+
} catch (\ValueError $e) {
65+
echo $e->getMessage(). PHP_EOL;
66+
}
67+
68+
try {
69+
ut_loc_locale_lookup(["de-DE"], "de-D\0E", true, "en-US");
70+
} catch (\ValueError $e) {
71+
echo $e->getMessage(). PHP_EOL;
72+
}
73+
74+
try {
75+
ut_loc_locale_lookup(["de-DE"], "de-DE", true, "e\0n-US");
76+
} catch (\ValueError $e) {
77+
echo $e->getMessage(). PHP_EOL;
78+
}
79+
6280
$res_str .= "\n";
6381
return $res_str;
6482

@@ -69,6 +87,12 @@ ut_run();
6987

7088
?>
7189
--EXPECT--
90+
Locale::lookup(): Argument #2 ($locale) must not contain any null bytes
91+
Locale::lookup(): Argument #2 ($locale) must not contain any null bytes
92+
Locale::lookup(): Argument #4 ($defaultLocale) must not contain any null bytes
93+
locale_lookup(): Argument #2 ($locale) must not contain any null bytes
94+
locale_lookup(): Argument #2 ($locale) must not contain any null bytes
95+
locale_lookup(): Argument #4 ($defaultLocale) must not contain any null bytes
7296
--------------
7397
loc_range:de-de
7498
lang_tags: de-DEVA,de-DE-1996,de-DE,zh_Hans,de-CH-1996,sl_IT,sl_IT_nedis-a-kirti-x-xyz,sl_IT_rozaj,sl_IT_NEDIS_ROJAZ_1901,i-enochian,sgn-CH-de,art-lojban,i-lux,art-lojban,jbo,en_sl_IT,zh-Hant-CN-x-prv1-prv2

ext/intl/tests/locale_set_default.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ function ut_main()
8686
$res_str .= "\n";
8787
}
8888

89+
try {
90+
ut_loc_set_default("a-\0DE");
91+
} catch (\ValueError $e) {
92+
echo $e->getMessage(), PHP_EOL;
93+
}
94+
8995
return $res_str;
9096

9197
}
@@ -95,6 +101,8 @@ ut_run();
95101

96102
?>
97103
--EXPECT--
104+
Locale::setDefault(): Argument #1 ($locale) must not contain any null bytes
105+
locale_set_default(): Argument #1 ($locale) must not contain any null bytes
98106
uk-ua_CALIFORNIA@currency=;currency=GRN: set locale 'uk-ua_CALIFORNIA@currency=;currency=GRN'
99107
root: set locale 'root'
100108
uk@currency=EURO: set locale 'uk@currency=EURO'

0 commit comments

Comments
 (0)