Skip to content

Commit 2da0d7e

Browse files
committed
Migrate zend_atol() calls to ZEND_ATOL() or zend_ini_parse_quantity()
1 parent 39d22de commit 2da0d7e

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
@@ -505,7 +505,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
505505

506506
/* Ignore trailing whitespace */
507507
while (str_len && ZEND_IS_WHITESPACE(str[str_len-1])) --str_len;
508-
if (!str_len) return 0;
508+
if (!str_len) {
509+
*errstr = NULL;
510+
return 0;
511+
}
509512

510513
/* Perform following multiplications on unsigned to avoid overflow UB.
511514
* For now overflow is silently ignored -- not clear what else can be
@@ -524,7 +527,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
524527
while (ZEND_IS_WHITESPACE(*digits_end)) ++digits_end;
525528

526529
/* No exponent suffix. */
527-
if (!*digits_end) return retval;
530+
if (!*digits_end) {
531+
*errstr = NULL;
532+
return retval;
533+
}
528534

529535
if (str_len>0) {
530536
switch (str[str_len-1]) {
@@ -552,8 +558,10 @@ ZEND_API zend_long zend_ini_parse_quantity(zend_string *value, zend_string **err
552558
/* More than one character in suffix */
553559
*errstr = zend_strpprintf(0, "Invalid numeric string '%.*s', interpreting as '%.*s%c' for backwards compatibility",
554560
(int)str_len, str, (int)(digits_end - str), str, str[str_len-1]);
561+
return (zend_long) retval;
555562
}
556563

564+
*errstr = NULL;
557565
return (zend_long) retval;
558566
}
559567
/* }}} */
@@ -646,14 +654,24 @@ ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
646654
ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
647655
{
648656
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
649-
*p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
657+
zend_string *errstr;
658+
*p = zend_ini_parse_quantity(new_value, &errstr);
659+
if (errstr) {
660+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
661+
zend_string_release(errstr);
662+
}
650663
return SUCCESS;
651664
}
652665
/* }}} */
653666

654667
ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
655668
{
656-
zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
669+
zend_string *errstr;
670+
zend_long tmp = zend_ini_parse_quantity(new_value, &errstr);
671+
if (errstr) {
672+
zend_error(E_WARNING, "Invalid \"%s\" setting: %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
673+
zend_string_release(errstr);
674+
}
657675
if (tmp < 0) {
658676
return FAILURE;
659677
}

Zend/zend_ini.h

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

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
@@ -2505,7 +2505,7 @@ static void php_simple_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int cal
25052505
}
25062506

25072507
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) {
2508-
zend_ulong key = (zend_ulong) zend_atol(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1));
2508+
zend_ulong key = (zend_ulong) ZEND_STRTOUL(Z_STRVAL_P(arg1), NULL, 0);
25092509
if ((find_hash = zend_hash_index_find(Z_ARRVAL_P(arr), key)) == NULL) {
25102510
array_init(&hash);
25112511
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
@@ -52,6 +52,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
5252
int replace_zend_execute_ex;
5353
int register_passes;
5454
zend_test_fiber *active_fiber;
55+
zend_long quantity_value;
5556
ZEND_END_MODULE_GLOBALS(zend_test)
5657

5758
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
@@ -310,7 +310,7 @@ static ZEND_FUNCTION(zend_get_unit_enum)
310310
static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
311311
{
312312
zend_string *str;
313-
zend_string *errstr = NULL;
313+
zend_string *errstr;
314314

315315
ZEND_PARSE_PARAMETERS_START(1, 1)
316316
Z_PARAM_STR(str)
@@ -319,7 +319,7 @@ static ZEND_FUNCTION(zend_test_zend_ini_parse_quantity)
319319
RETVAL_LONG(zend_ini_parse_quantity(str, &errstr));
320320

321321
if (errstr) {
322-
zend_error(E_WARNING, "%s", errstr);
322+
zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
323323
zend_string_release(errstr);
324324
}
325325
}
@@ -445,6 +445,7 @@ static ZEND_METHOD(ZendTestNS2_ZendSubNS_Foo, method)
445445
PHP_INI_BEGIN()
446446
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)
447447
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
448+
STD_PHP_INI_ENTRY("zend_test.quantity_value", "0", PHP_INI_ALL, OnUpdateLong, quantity_value, zend_zend_test_globals, zend_test_globals)
448449
PHP_INI_END()
449450

450451
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
@@ -578,7 +579,10 @@ ZEND_GET_MODULE(zend_test)
578579
/* The important part here is the ZEND_FASTCALL. */
579580
PHP_ZEND_TEST_API int ZEND_FASTCALL bug78270(const char *str, size_t str_len)
580581
{
581-
return (int) zend_atol(str, str_len);
582+
char * copy = zend_strndup(str, str_len);
583+
int r = (int) ZEND_ATOL(copy);
584+
free(copy);
585+
return r;
582586
}
583587

584588
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)