Skip to content

Commit 1301be7

Browse files
author
Sjoerd Langkemper
committed
Warn when number base conversion loses precision
_php_math_basetozval is used for base_convert, bindec, hexdec and octdec. It uses an integer or double for the internal representation of the number. When the input number is too large to fit in there, it loses precision. This commit emits a notice when this happens. Discussion thread: https://news-web.php.net/php.internals/131364
1 parent e71b4e5 commit 1301be7

5 files changed

Lines changed: 59 additions & 4 deletions

File tree

ext/standard/math.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ PHPAPI void _php_math_basetozval(zend_string *str, int base, zval *ret)
898898
num = num * base + c;
899899
break;
900900
} else {
901+
zend_error(E_NOTICE, "Input number exceeds maximum integer value, precision has been lost in conversion");
901902
fnum = (double)num;
902903
mode = 1;
903904
}

ext/standard/tests/math/base_convert_basic.phpt

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ $values = array(10,
1414
"27",
1515
"39",
1616
"5F",
17-
"3XYZ"
17+
"3XYZ",
18+
"1111111111111111"
1819
);
1920

2021
for ($f= 0; $f < count($frombase); $f++) {
@@ -57,6 +58,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
5758

5859
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
5960
.........value= 3XYZ res = 0
61+
.........value= 1111111111111111 res = 1111111111111111
6062
......to base is 8
6163
.........value= 10 res = 2
6264

@@ -84,6 +86,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
8486

8587
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
8688
.........value= 3XYZ res = 0
89+
.........value= 1111111111111111 res = 177777
8790
......to base is 10
8891
.........value= 10 res = 2
8992

@@ -111,6 +114,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
111114

112115
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
113116
.........value= 3XYZ res = 0
117+
.........value= 1111111111111111 res = 65535
114118
......to base is 16
115119
.........value= 10 res = 2
116120

@@ -138,6 +142,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
138142

139143
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
140144
.........value= 3XYZ res = 0
145+
.........value= 1111111111111111 res = ffff
141146
......to base is 36
142147
.........value= 10 res = 2
143148

@@ -165,6 +170,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
165170

166171
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
167172
.........value= 3XYZ res = 0
173+
.........value= 1111111111111111 res = 1ekf
168174

169175
...from base is 8
170176
......to base is 2
@@ -188,6 +194,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
188194

189195
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
190196
.........value= 3XYZ res = 11
197+
.........value= 1111111111111111 res = 1001001001001001001001001001001001001001001001
191198
......to base is 8
192199
.........value= 10 res = 10
193200
.........value= 27 res = 27
@@ -209,6 +216,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
209216

210217
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
211218
.........value= 3XYZ res = 3
219+
.........value= 1111111111111111 res = 1111111111111111
212220
......to base is 10
213221
.........value= 10 res = 8
214222
.........value= 27 res = 23
@@ -230,6 +238,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
230238

231239
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
232240
.........value= 3XYZ res = 3
241+
.........value= 1111111111111111 res = 40210710958665
233242
......to base is 16
234243
.........value= 10 res = 8
235244
.........value= 27 res = 17
@@ -251,6 +260,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
251260

252261
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
253262
.........value= 3XYZ res = 3
263+
.........value= 1111111111111111 res = 249249249249
254264
......to base is 36
255265
.........value= 10 res = 8
256266
.........value= 27 res = n
@@ -272,6 +282,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
272282

273283
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
274284
.........value= 3XYZ res = 3
285+
.........value= 1111111111111111 res = e94jn3f49
275286

276287
...from base is 10
277288
......to base is 2
@@ -289,6 +300,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
289300

290301
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
291302
.........value= 3XYZ res = 11
303+
.........value= 1111111111111111 res = 11111100101000110010110111000101010111000111000111
292304
......to base is 8
293305
.........value= 10 res = 12
294306
.........value= 27 res = 33
@@ -304,6 +316,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
304316

305317
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
306318
.........value= 3XYZ res = 3
319+
.........value= 1111111111111111 res = 37450626705270707
307320
......to base is 10
308321
.........value= 10 res = 10
309322
.........value= 27 res = 27
@@ -319,6 +332,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
319332

320333
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
321334
.........value= 3XYZ res = 3
335+
.........value= 1111111111111111 res = 1111111111111111
322336
......to base is 16
323337
.........value= 10 res = a
324338
.........value= 27 res = 1b
@@ -334,6 +348,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
334348

335349
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
336350
.........value= 3XYZ res = 3
351+
.........value= 1111111111111111 res = 3f28cb71571c7
337352
......to base is 36
338353
.........value= 10 res = a
339354
.........value= 27 res = r
@@ -349,6 +364,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
349364

350365
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
351366
.........value= 3XYZ res = 3
367+
.........value= 1111111111111111 res = axutebils7
352368

353369
...from base is 16
354370
......to base is 2
@@ -364,6 +380,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
364380

365381
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
366382
.........value= 3XYZ res = 11
383+
.........value= 1111111111111111 res = 1000100010001000100010001000100010001000100010001000100010001
367384
......to base is 8
368385
.........value= 10 res = 20
369386
.........value= 27 res = 47
@@ -377,6 +394,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
377394

378395
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
379396
.........value= 3XYZ res = 3
397+
.........value= 1111111111111111 res = 104210421042104210421
380398
......to base is 10
381399
.........value= 10 res = 16
382400
.........value= 27 res = 39
@@ -390,6 +408,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
390408

391409
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
392410
.........value= 3XYZ res = 3
411+
.........value= 1111111111111111 res = 1229782938247303441
393412
......to base is 16
394413
.........value= 10 res = 10
395414
.........value= 27 res = 27
@@ -403,6 +422,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
403422

404423
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
405424
.........value= 3XYZ res = 3
425+
.........value= 1111111111111111 res = 1111111111111111
406426
......to base is 36
407427
.........value= 10 res = g
408428
.........value= 27 res = 13
@@ -416,6 +436,7 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
416436

417437
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
418438
.........value= 3XYZ res = 3
439+
.........value= 1111111111111111 res = 9ccxo2jlx3ip
419440

420441
...from base is 36
421442
......to base is 2
@@ -429,6 +450,9 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
429450
.........value= 39 res = 1110101
430451
.........value= 5F res = 11000011
431452
.........value= 3XYZ res = 101100111010111011
453+
454+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
455+
.........value= 1111111111111111 res = 1101101010010011001001100101101101110100000000000000000000000000
432456
......to base is 8
433457
.........value= 10 res = 44
434458
.........value= 27 res = 117
@@ -440,6 +464,9 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
440464
.........value= 39 res = 165
441465
.........value= 5F res = 303
442466
.........value= 3XYZ res = 547273
467+
468+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
469+
.........value= 1111111111111111 res = 60115552231145556400000000
443470
......to base is 10
444471
.........value= 10 res = 36
445472
.........value= 27 res = 79
@@ -451,6 +478,9 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
451478
.........value= 39 res = 117
452479
.........value= 5F res = 195
453480
.........value= 3XYZ res = 183995
481+
482+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
483+
.........value= 1111111111111111 res = 227390317427040000046866
454484
......to base is 16
455485
.........value= 10 res = 24
456486
.........value= 27 res = 4f
@@ -462,6 +492,9 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
462492
.........value= 39 res = 75
463493
.........value= 5F res = c3
464494
.........value= 3XYZ res = 2cebb
495+
496+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
497+
.........value= 1111111111111111 res = 3026da93265b74000000
465498
......to base is 36
466499
.........value= 10 res = 10
467500
.........value= 27 res = 27
@@ -473,3 +506,6 @@ Deprecated: Invalid characters passed for attempted conversion, these have been
473506
.........value= 39 res = 39
474507
.........value= 5F res = 5f
475508
.........value= 3XYZ res = 3xyz
509+
510+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
511+
.........value= 1111111111111111 res = 11111111111wsws0

ext/standard/tests/math/bindec_basiclong_64bit.phpt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,24 @@ foreach ($binLongStrs as $strVal) {
3030
}
3131

3232
?>
33-
--EXPECT--
33+
--EXPECTF--
3434
--- testing: 0111111111111111111111111111111111111111111111111111111111111111 ---
3535
int(9223372036854775807)
3636
--- testing: 1111111111111111111111111111111111111111111111111111111111111111 ---
37+
38+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
3739
float(1.8446744073709552E+19)
3840
--- testing: 01111111111111111111111111111111 ---
3941
int(2147483647)
4042
--- testing: 11111111111111111111111111111111 ---
4143
int(4294967295)
4244
--- testing: 01111111111111111111111111111111111111111111111111111111111111111 ---
45+
46+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4347
float(1.8446744073709552E+19)
4448
--- testing: 11111111111111111111111111111111111111111111111111111111111111111 ---
49+
50+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4551
float(3.6893488147419103E+19)
4652
--- testing: 011111111111111111111111111111111 ---
4753
int(4294967295)

ext/standard/tests/math/hexdec_basiclong_64bit.phpt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,24 @@ foreach ($hexLongStrs as $strVal) {
3030
}
3131

3232
?>
33-
--EXPECT--
33+
--EXPECTF--
3434
--- testing: 7fffffffffffffff ---
3535
int(9223372036854775807)
3636
--- testing: ffffffffffffffff ---
37+
38+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
3739
float(1.8446744073709552E+19)
3840
--- testing: 7fffffff ---
3941
int(2147483647)
4042
--- testing: ffffffff ---
4143
int(4294967295)
4244
--- testing: 7ffffffffffffffff ---
45+
46+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4347
float(1.4757395258967641E+20)
4448
--- testing: ffffffffffffffffff ---
49+
50+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4551
float(4.722366482869645E+21)
4652
--- testing: 7ffffffff ---
4753
int(34359738367)

ext/standard/tests/math/octdec_basiclong_64bit.phpt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,24 @@ foreach ($octLongStrs as $strVal) {
3030
}
3131

3232
?>
33-
--EXPECT--
33+
--EXPECTF--
3434
--- testing: 777777777777777777777 ---
3535
int(9223372036854775807)
3636
--- testing: 1777777777777777777777 ---
37+
38+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
3739
float(1.8446744073709552E+19)
3840
--- testing: 17777777777 ---
3941
int(2147483647)
4042
--- testing: 37777777777 ---
4143
int(4294967295)
4244
--- testing: 377777777777777777777777 ---
45+
46+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4347
float(2.3611832414348226E+21)
4448
--- testing: 17777777777777777777777777 ---
49+
50+
Notice: Input number exceeds maximum integer value, precision has been lost in conversion in %s on line %d
4551
float(7.555786372591432E+22)
4652
--- testing: 377777777777 ---
4753
int(34359738367)

0 commit comments

Comments
 (0)