Skip to content

Commit 9874acf

Browse files
committed
Migrate zend_atol() calls to ZEND_ATOL() or zend_ini_parse_quantity()
1 parent e6332cc commit 9874acf

File tree

12 files changed

+130
-25
lines changed

12 files changed

+130
-25
lines changed

Zend/zend.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,13 @@ static ZEND_INI_MH(OnUpdateScriptEncoding) /* {{{ */
145145
static ZEND_INI_MH(OnUpdateAssertions) /* {{{ */
146146
{
147147
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
148+
zend_string *errstr;
148149

149-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
150+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
151+
if (errstr) {
152+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
153+
zend_string_release(errstr);
154+
}
150155

151156
if (stage != ZEND_INI_STAGE_STARTUP &&
152157
stage != ZEND_INI_STAGE_SHUTDOWN &&
@@ -175,8 +180,13 @@ static ZEND_INI_MH(OnSetExceptionStringParamMaxLen) /* {{{ */
175180

176181
static ZEND_INI_MH(OnUpdateFiberStackSize) /* {{{ */
177182
{
183+
zend_string *errstr;
178184
if (new_value) {
179-
EG(fiber_stack_size) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
185+
EG(fiber_stack_size) = zend_ini_parse_quantity(new_value, &errstr);
186+
if (errstr) {
187+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
188+
zend_string_release(errstr);
189+
}
180190
} else {
181191
EG(fiber_stack_size) = ZEND_FIBER_DEFAULT_C_STACK_SIZE;
182192
}

Zend/zend_ini.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
546546

547547
/* Ignore trailing whitespace */
548548
while (str_len && ZEND_IS_WHITESPACE(str[str_len-1])) --str_len;
549-
if (!str_len) return 0;
549+
if (!str_len) {
550+
*errstr = NULL;
551+
return 0;
552+
}
550553

551554
/* Perform following multiplications on unsigned to avoid overflow UB.
552555
* For now overflow is silently ignored -- not clear what else can be
@@ -565,7 +568,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
565568
while (ZEND_IS_WHITESPACE(*digits_end)) ++digits_end;
566569

567570
/* No exponent suffix. */
568-
if (!*digits_end) return retval;
571+
if (!*digits_end) {
572+
*errstr = NULL;
573+
return retval;
574+
}
569575

570576
if (str_len>0) {
571577
switch (str[str_len-1]) {
@@ -593,8 +599,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
593599
/* More than one character in suffix */
594600
*errstr = zend_strpprintf(0, "Invalid numeric string '%.*s', interpreting as '%.*s%c' for backwards compatibility",
595601
(int)str_len, str, (int)(digits_end - str), str, str[str_len-1]);
602+
return (zend_long) retval;
596603
}
597604

605+
*errstr = NULL;
598606
return (zend_long) retval;
599607
}
600608
/* }}} */
@@ -687,14 +695,24 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
687695
ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
688696
{
689697
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
690-
*p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
698+
zend_string *errstr;
699+
*p = zend_ini_parse_quantity(new_value, &errstr);
700+
if (errstr) {
701+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
702+
zend_string_release(errstr);
703+
}
691704
return SUCCESS;
692705
}
693706
/* }}} */
694707

695708
ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
696709
{
697-
zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
710+
zend_string *errstr;
711+
zend_long tmp = zend_ini_parse_quantity(new_value, &errstr);
712+
if (errstr) {
713+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
714+
zend_string_release(errstr);
715+
}
698716
if (tmp < 0) {
699717
return FAILURE;
700718
}

Zend/zend_ini.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,16 @@ ZEND_API bool zend_ini_parse_bool(zend_string *str);
9999
* The digits are parsed as decimal unless the first character is '0', in which
100100
* case they are parsed as octal.
101101
*
102-
* Whitespaces before and after the digits portion are ignored.
102+
* Whitespaces before and after the multiplier are ignored.
103103
*
104-
* For backwards compatibility, invalid values are handled as follows:
104+
* For backwards compatibility, ill-formatted values are handled as follows:
105105
* - No leading digits: value is treated as '0'
106106
* - Invalid multiplier: multiplier is ignored
107107
* - Invalid characters between digits and multiplier: invalid characters are
108108
* ignored
109109
*
110-
* In all of these cases an error string is stored in *errstr (caller must
111-
* release it).
110+
* In any of these cases an error string is stored in *errstr (caller must
111+
* release it), otherwise *errstr is set to NULL.
112112
*/
113113
ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **errstr);
114114

Zend/zend_operators.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = {
118118
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
119119
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
120120
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
121-
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
121+
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
122122
};
123123

124124

@@ -136,7 +136,7 @@ ZEND_API const unsigned char zend_toupper_map[256] = {
136136
zend_binary_strncasecmp
137137
*/
138138

139-
ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* {{{ */
139+
static zend_long ZEND_FASTCALL zend_atol_internal(const char *str, size_t str_len) /* {{{ */
140140
{
141141
if (!str_len) {
142142
str_len = strlen(str);
@@ -168,9 +168,14 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len) /* {
168168
}
169169
/* }}} */
170170

171+
ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, size_t str_len)
172+
{
173+
return zend_atol_internal(str, str_len);
174+
}
175+
171176
ZEND_API int ZEND_FASTCALL zend_atoi(const char *str, size_t str_len)
172177
{
173-
return (int) zend_atol(str, str_len);
178+
return (int) zend_atol_internal(str, str_len);
174179
}
175180

176181
/* {{{ convert_object_to_type: dst will be either ctype or UNDEF */

ext/bcmath/bcmath.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ ZEND_INI_MH(OnUpdateScale)
6161
{
6262
int *p;
6363
zend_long tmp;
64+
zend_string *errstr;
6465

65-
tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
66+
tmp = zend_ini_parse_quantity(new_value, &errstr);
67+
if (errstr) {
68+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
69+
zend_string_release(errstr);
70+
}
6671
if (tmp < 0 || tmp > INT_MAX) {
6772
return FAILURE;
6873
}

ext/opcache/zend_accelerator_module.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,12 @@ static ZEND_INI_MH(OnUpdateJit)
165165
static ZEND_INI_MH(OnUpdateJitDebug)
166166
{
167167
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
168-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
168+
zend_string *errstr;
169+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
170+
if (errstr) {
171+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
172+
zend_string_release(errstr);
173+
}
169174

170175
if (zend_jit_debug_config(*p, val, stage) == SUCCESS) {
171176
*p = val;
@@ -176,7 +181,13 @@ static ZEND_INI_MH(OnUpdateJitDebug)
176181

177182
static ZEND_INI_MH(OnUpdateCounter)
178183
{
179-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
184+
zend_string *errstr;
185+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
186+
if (errstr) {
187+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
188+
zend_string_release(errstr);
189+
}
190+
180191
if (val >= 0 && val < 256) {
181192
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
182193
*p = val;
@@ -188,7 +199,13 @@ static ZEND_INI_MH(OnUpdateCounter)
188199

189200
static ZEND_INI_MH(OnUpdateUnrollC)
190201
{
191-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
202+
zend_string *errstr;
203+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
204+
if (errstr) {
205+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
206+
zend_string_release(errstr);
207+
}
208+
192209
if (val > 0 && val < ZEND_JIT_TRACE_MAX_CALL_DEPTH) {
193210
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
194211
*p = val;
@@ -201,7 +218,13 @@ static ZEND_INI_MH(OnUpdateUnrollC)
201218

202219
static ZEND_INI_MH(OnUpdateUnrollR)
203220
{
204-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
221+
zend_string *errstr;
222+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
223+
if (errstr) {
224+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
225+
zend_string_release(errstr);
226+
}
227+
205228
if (val >= 0 && val < ZEND_JIT_TRACE_MAX_RET_DEPTH) {
206229
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
207230
*p = val;
@@ -214,7 +237,13 @@ static ZEND_INI_MH(OnUpdateUnrollR)
214237

215238
static ZEND_INI_MH(OnUpdateUnrollL)
216239
{
217-
zend_long val = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
240+
zend_string *errstr;
241+
zend_long val = zend_ini_parse_quantity(new_value, &errstr);
242+
if (errstr) {
243+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
244+
zend_string_release(errstr);
245+
}
246+
218247
if (val > 0 && val < ZEND_JIT_TRACE_MAX_LOOPS_UNROLL) {
219248
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
220249
*p = val;

ext/standard/basic_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2506,7 +2506,7 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int cal
25062506
}
25072507

25082508
if (!(Z_STRLEN_P(arg1) > 1 && Z_STRVAL_P(arg1)[0] == '0') && is_numeric_string(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), NULL, NULL, 0) == IS_LONG) {
2509-
zend_ulong key = (zend_ulong) zend_atol(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
2509+
zend_ulong key = (zend_ulong) ZEND_STRTOUL(Z_STRVAL_P(arg1), NULL, 0);
25102510
if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
25112511
array_init(&hash);
25122512
find_hash = zend_hash_index_add_new(Z_ARRVAL_P(arr), key, &hash);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
parse_ini_string with numeric entry name
3+
--FILE--
4+
<?php
5+
6+
var_dump(parse_ini_string("
7+
1[]=1
8+
2M[]=2
9+
"));
10+
11+
--EXPECT--
12+
array(2) {
13+
[1]=>
14+
array(1) {
15+
[0]=>
16+
string(1) "1"
17+
}
18+
["2M"]=>
19+
array(1) {
20+
[0]=>
21+
string(1) "2"
22+
}
23+
}

ext/zend_test/php_test.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
5353
int register_passes;
5454
bool print_stderr_mshutdown;
5555
zend_test_fiber *active_fiber;
56+
zend_long quantity_value;
5657
ZEND_END_MODULE_GLOBALS(zend_test)
5758

5859
extern ZEND_DECLARE_MODULE_GLOBALS(zend_test)

ext/zend_test/test.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ static ZEND_FUNCTION(zend_get_unit_enum)
359359
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
360360
{
361361
zend_string *str;
362-
zend_string *errstr = NULL;
362+
zend_string *errstr;
363363

364364
ZEND_PARSE_PARAMETERS_START(1, 1)
365365
Z_PARAM_STR(str)
@@ -368,7 +368,7 @@ static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
368368
RETVAL_LONG(zend_ini_parse_quantity(str, &errstr));
369369

370370
if (errstr) {
371-
zend_error(E_WARNING, "%s", errstr);
371+
zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
372372
zend_string_release(errstr);
373373
}
374374
}
@@ -550,6 +550,7 @@ PHP_INI_BEGIN()
550550
STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
551551
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
552552
STD_PHP_INI_BOOLEAN("zend_test.print_stderr_mshutdown", "0", PHP_INI_SYSTEM, OnUpdateBool, print_stderr_mshutdown, zend_zend_test_globals, zend_test_globals)
553+
STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
553554
PHP_INI_END()
554555

555556
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
@@ -743,7 +744,10 @@ ZEND_GET_MODULE(zend_test)
743744
/* The important part here is the ZEND_FASTCALL. */
744745
PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len)
745746
{
746-
return (int) zend_atol(str, str_len);
747+
char * copy = zend_strndup(str, str_len);
748+
int r = (int) ZEND_ATOL(copy);
749+
free(copy);
750+
return r;
747751
}
748752

749753
PHP_ZEND_TEST_API struct bug79096 bug79096(void)

ext/zlib/zlib.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
12681268
{
12691269
int int_value;
12701270
char *ini_value;
1271+
zend_string *errstr = NULL;
12711272
if (new_value == NULL) {
12721273
return FAILURE;
12731274
}
@@ -1277,7 +1278,11 @@ static PHP_INI_MH(OnUpdate_zlib_output_compression)
12771278
} else if (zend_string_equals_literal_ci(new_value, "on")) {
12781279
int_value = 1;
12791280
} else {
1280-
int_value = zend_atoi(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
1281+
int_value = (int) zend_ini_parse_quantity(new_value, &errstr);
1282+
if (errstr) {
1283+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
1284+
zend_string_release(errstr);
1285+
}
12811286
}
12821287
ini_value = zend_ini_string("output_handler", sizeof("output_handler"), 0);
12831288

main/main.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,13 @@ static PHP_INI_MH(OnSetSerializePrecision)
262262
static PHP_INI_MH(OnChangeMemoryLimit)
263263
{
264264
size_t value;
265+
zend_string *errstr;
265266
if (new_value) {
266-
value = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
267+
value = zend_ini_parse_quantity(new_value, &errstr);
268+
if (errstr) {
269+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
270+
zend_string_release(errstr);
271+
}
267272
} else {
268273
value = Z_L(1)<<30; /* effectively, no limit */
269274
}

0 commit comments

Comments
 (0)