Skip to content

Commit c7e9758

Browse files
arnaud-lbsgolemon
andcommitted
Add zend_ini_parse_quantity() and deprecate zend_atol(), zend_atoi()
zend_atol() and zend_atoi() don't just do number parsing. They also check for a 'K', 'M', or 'G' at the end of the string, and multiply the parsed value out accordingly. Unfortunately, they ignore any other non-numerics between the numeric component and the last character in the string. This means that numbers such as the following are both valid and non-intuitive in their final output. * "123KMG" is interpreted as "123G" -> 132070244352 * "123G " is interpreted as "123 " -> 123 * "123GB" is interpreted as "123B" -> 123 * "123 I like tacos." is also interpreted as "123." -> 123 Currently, in php-src these functions are used only for parsing ini values. In this change we deprecate zend_atol(), zend_atoi(), and introduce a new function with the same behaviour, but with the ability to report invalid inputs to the caller. The function's name also makes the behaviour less unexpected: zend_ini_parse_quantity(). Co-authored-by: Sara Golemon <pollita@php.net>
1 parent 313371a commit c7e9758

File tree

8 files changed

+508
-3
lines changed

8 files changed

+508
-3
lines changed
Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
--TEST--
2+
Test parsing of quantities (e.g. "16M")
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
8+
// This test checks valid formats do not throw any warnings.
9+
foreach (['', ' '] as $leadingWS) {
10+
foreach (['', '+', '-'] as $sign) {
11+
foreach (['', ' '] as $midWS) {
12+
foreach (['', 'K', 'k', 'M', 'm', 'G', 'g'] as $exp) {
13+
foreach (['', ' '] as $trailingWS) {
14+
$setting = sprintf('%s%s1%s%s%s',
15+
$leadingWS, $sign, $midWS, $exp, $trailingWS);
16+
var_dump($setting);
17+
var_dump(zend_test_zend_ini_parse_quantity($setting));
18+
}
19+
}
20+
}
21+
}
22+
}
23+
24+
--EXPECT--
25+
string(1) "1"
26+
int(1)
27+
string(2) "1 "
28+
int(1)
29+
string(2) "1K"
30+
int(1024)
31+
string(3) "1K "
32+
int(1024)
33+
string(2) "1k"
34+
int(1024)
35+
string(3) "1k "
36+
int(1024)
37+
string(2) "1M"
38+
int(1048576)
39+
string(3) "1M "
40+
int(1048576)
41+
string(2) "1m"
42+
int(1048576)
43+
string(3) "1m "
44+
int(1048576)
45+
string(2) "1G"
46+
int(1073741824)
47+
string(3) "1G "
48+
int(1073741824)
49+
string(2) "1g"
50+
int(1073741824)
51+
string(3) "1g "
52+
int(1073741824)
53+
string(2) "1 "
54+
int(1)
55+
string(3) "1 "
56+
int(1)
57+
string(3) "1 K"
58+
int(1024)
59+
string(4) "1 K "
60+
int(1024)
61+
string(3) "1 k"
62+
int(1024)
63+
string(4) "1 k "
64+
int(1024)
65+
string(3) "1 M"
66+
int(1048576)
67+
string(4) "1 M "
68+
int(1048576)
69+
string(3) "1 m"
70+
int(1048576)
71+
string(4) "1 m "
72+
int(1048576)
73+
string(3) "1 G"
74+
int(1073741824)
75+
string(4) "1 G "
76+
int(1073741824)
77+
string(3) "1 g"
78+
int(1073741824)
79+
string(4) "1 g "
80+
int(1073741824)
81+
string(2) "+1"
82+
int(1)
83+
string(3) "+1 "
84+
int(1)
85+
string(3) "+1K"
86+
int(1024)
87+
string(4) "+1K "
88+
int(1024)
89+
string(3) "+1k"
90+
int(1024)
91+
string(4) "+1k "
92+
int(1024)
93+
string(3) "+1M"
94+
int(1048576)
95+
string(4) "+1M "
96+
int(1048576)
97+
string(3) "+1m"
98+
int(1048576)
99+
string(4) "+1m "
100+
int(1048576)
101+
string(3) "+1G"
102+
int(1073741824)
103+
string(4) "+1G "
104+
int(1073741824)
105+
string(3) "+1g"
106+
int(1073741824)
107+
string(4) "+1g "
108+
int(1073741824)
109+
string(3) "+1 "
110+
int(1)
111+
string(4) "+1 "
112+
int(1)
113+
string(4) "+1 K"
114+
int(1024)
115+
string(5) "+1 K "
116+
int(1024)
117+
string(4) "+1 k"
118+
int(1024)
119+
string(5) "+1 k "
120+
int(1024)
121+
string(4) "+1 M"
122+
int(1048576)
123+
string(5) "+1 M "
124+
int(1048576)
125+
string(4) "+1 m"
126+
int(1048576)
127+
string(5) "+1 m "
128+
int(1048576)
129+
string(4) "+1 G"
130+
int(1073741824)
131+
string(5) "+1 G "
132+
int(1073741824)
133+
string(4) "+1 g"
134+
int(1073741824)
135+
string(5) "+1 g "
136+
int(1073741824)
137+
string(2) "-1"
138+
int(-1)
139+
string(3) "-1 "
140+
int(-1)
141+
string(3) "-1K"
142+
int(-1024)
143+
string(4) "-1K "
144+
int(-1024)
145+
string(3) "-1k"
146+
int(-1024)
147+
string(4) "-1k "
148+
int(-1024)
149+
string(3) "-1M"
150+
int(-1048576)
151+
string(4) "-1M "
152+
int(-1048576)
153+
string(3) "-1m"
154+
int(-1048576)
155+
string(4) "-1m "
156+
int(-1048576)
157+
string(3) "-1G"
158+
int(-1073741824)
159+
string(4) "-1G "
160+
int(-1073741824)
161+
string(3) "-1g"
162+
int(-1073741824)
163+
string(4) "-1g "
164+
int(-1073741824)
165+
string(3) "-1 "
166+
int(-1)
167+
string(4) "-1 "
168+
int(-1)
169+
string(4) "-1 K"
170+
int(-1024)
171+
string(5) "-1 K "
172+
int(-1024)
173+
string(4) "-1 k"
174+
int(-1024)
175+
string(5) "-1 k "
176+
int(-1024)
177+
string(4) "-1 M"
178+
int(-1048576)
179+
string(5) "-1 M "
180+
int(-1048576)
181+
string(4) "-1 m"
182+
int(-1048576)
183+
string(5) "-1 m "
184+
int(-1048576)
185+
string(4) "-1 G"
186+
int(-1073741824)
187+
string(5) "-1 G "
188+
int(-1073741824)
189+
string(4) "-1 g"
190+
int(-1073741824)
191+
string(5) "-1 g "
192+
int(-1073741824)
193+
string(2) " 1"
194+
int(1)
195+
string(3) " 1 "
196+
int(1)
197+
string(3) " 1K"
198+
int(1024)
199+
string(4) " 1K "
200+
int(1024)
201+
string(3) " 1k"
202+
int(1024)
203+
string(4) " 1k "
204+
int(1024)
205+
string(3) " 1M"
206+
int(1048576)
207+
string(4) " 1M "
208+
int(1048576)
209+
string(3) " 1m"
210+
int(1048576)
211+
string(4) " 1m "
212+
int(1048576)
213+
string(3) " 1G"
214+
int(1073741824)
215+
string(4) " 1G "
216+
int(1073741824)
217+
string(3) " 1g"
218+
int(1073741824)
219+
string(4) " 1g "
220+
int(1073741824)
221+
string(3) " 1 "
222+
int(1)
223+
string(4) " 1 "
224+
int(1)
225+
string(4) " 1 K"
226+
int(1024)
227+
string(5) " 1 K "
228+
int(1024)
229+
string(4) " 1 k"
230+
int(1024)
231+
string(5) " 1 k "
232+
int(1024)
233+
string(4) " 1 M"
234+
int(1048576)
235+
string(5) " 1 M "
236+
int(1048576)
237+
string(4) " 1 m"
238+
int(1048576)
239+
string(5) " 1 m "
240+
int(1048576)
241+
string(4) " 1 G"
242+
int(1073741824)
243+
string(5) " 1 G "
244+
int(1073741824)
245+
string(4) " 1 g"
246+
int(1073741824)
247+
string(5) " 1 g "
248+
int(1073741824)
249+
string(3) " +1"
250+
int(1)
251+
string(4) " +1 "
252+
int(1)
253+
string(4) " +1K"
254+
int(1024)
255+
string(5) " +1K "
256+
int(1024)
257+
string(4) " +1k"
258+
int(1024)
259+
string(5) " +1k "
260+
int(1024)
261+
string(4) " +1M"
262+
int(1048576)
263+
string(5) " +1M "
264+
int(1048576)
265+
string(4) " +1m"
266+
int(1048576)
267+
string(5) " +1m "
268+
int(1048576)
269+
string(4) " +1G"
270+
int(1073741824)
271+
string(5) " +1G "
272+
int(1073741824)
273+
string(4) " +1g"
274+
int(1073741824)
275+
string(5) " +1g "
276+
int(1073741824)
277+
string(4) " +1 "
278+
int(1)
279+
string(5) " +1 "
280+
int(1)
281+
string(5) " +1 K"
282+
int(1024)
283+
string(6) " +1 K "
284+
int(1024)
285+
string(5) " +1 k"
286+
int(1024)
287+
string(6) " +1 k "
288+
int(1024)
289+
string(5) " +1 M"
290+
int(1048576)
291+
string(6) " +1 M "
292+
int(1048576)
293+
string(5) " +1 m"
294+
int(1048576)
295+
string(6) " +1 m "
296+
int(1048576)
297+
string(5) " +1 G"
298+
int(1073741824)
299+
string(6) " +1 G "
300+
int(1073741824)
301+
string(5) " +1 g"
302+
int(1073741824)
303+
string(6) " +1 g "
304+
int(1073741824)
305+
string(3) " -1"
306+
int(-1)
307+
string(4) " -1 "
308+
int(-1)
309+
string(4) " -1K"
310+
int(-1024)
311+
string(5) " -1K "
312+
int(-1024)
313+
string(4) " -1k"
314+
int(-1024)
315+
string(5) " -1k "
316+
int(-1024)
317+
string(4) " -1M"
318+
int(-1048576)
319+
string(5) " -1M "
320+
int(-1048576)
321+
string(4) " -1m"
322+
int(-1048576)
323+
string(5) " -1m "
324+
int(-1048576)
325+
string(4) " -1G"
326+
int(-1073741824)
327+
string(5) " -1G "
328+
int(-1073741824)
329+
string(4) " -1g"
330+
int(-1073741824)
331+
string(5) " -1g "
332+
int(-1073741824)
333+
string(4) " -1 "
334+
int(-1)
335+
string(5) " -1 "
336+
int(-1)
337+
string(5) " -1 K"
338+
int(-1024)
339+
string(6) " -1 K "
340+
int(-1024)
341+
string(5) " -1 k"
342+
int(-1024)
343+
string(6) " -1 k "
344+
int(-1024)
345+
string(5) " -1 M"
346+
int(-1048576)
347+
string(6) " -1 M "
348+
int(-1048576)
349+
string(5) " -1 m"
350+
int(-1048576)
351+
string(6) " -1 m "
352+
int(-1048576)
353+
string(5) " -1 G"
354+
int(-1073741824)
355+
string(6) " -1 G "
356+
int(-1073741824)
357+
string(5) " -1 g"
358+
int(-1073741824)
359+
string(6) " -1 g "
360+
int(-1073741824)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Test parsing of quantities (e.g. "16M"): errors
3+
--EXTENSIONS--
4+
zend_test
5+
--FILE--
6+
<?php
7+
8+
// This test checks invalid formats do throw warnings.
9+
10+
$tests = [
11+
'K', # No digits
12+
'1KM', # Multiple multipliers.
13+
'1X', # Unknown multiplier.
14+
'1.0K', # Non integral digits.
15+
];
16+
17+
foreach ($tests as $setting) {
18+
var_dump(zend_test_zend_ini_parse_quantity($setting));
19+
}
20+
21+
--EXPECTF--
22+
Warning: Invalid numeric string 'K': no valid leading digits, interpreting as '0' for backwards compatibility in %s%ezend_ini_parse_quantity_error.php on line %d
23+
int(0)
24+
25+
Warning: Invalid numeric string '1KM', interpreting as '1M' for backwards compatibility in %s%ezend_ini_parse_quantity_error.php on line %d
26+
int(1048576)
27+
28+
Warning: Invalid numeric string '1X': unknown multipler 'X', interpreting as '1' for backwards compatibility in %s%ezend_ini_parse_quantity_error.php on line %d
29+
int(1)
30+
31+
Warning: Invalid numeric string '1.0K', interpreting as '1K' for backwards compatibility in %s%ezend_ini_parse_quantity_error.php on line %d
32+
int(1024)

0 commit comments

Comments
 (0)