Commit 5eb9bbddb4c for php.net
commit 5eb9bbddb4cb4c8cd0560ad933f27514cbaf9e91
Author: Sjoerd Langkemper <sjoerd-github@linuxonly.nl>
Date: Wed Jul 29 20:42:55 2026 +0200
ext/standard: Warn when number base conversion loses precision (#22371)
_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
PR: https://github.com/php/php-src/pull/22371
diff --git a/NEWS b/NEWS
index c144b3c62c2..cb70bda237f 100644
--- a/NEWS
+++ b/NEWS
@@ -276,6 +276,8 @@ PHP NEWS
(David Carlier)
. TSRM: make CG, EG, SCNG and AG compile-time offsets. (henderkes)
. Deprecate returning values from __construct() and __destruct(). (timwolla)
+ . base_convert, bindex, hexdec and octdec now raise a notice when they cannot
+ precisely convert the given number. (Sjoerd Langkemper)
- BCMath:
. Added NUL-byte validation to BCMath functions. (jorgsowa)
diff --git a/Zend/tests/zend_ini/zend_ini_parse_uquantity_overflow.phpt b/Zend/tests/zend_ini/zend_ini_parse_uquantity_overflow.phpt
index 0da9c4fac97..f770ccbcaf2 100644
--- a/Zend/tests/zend_ini/zend_ini_parse_uquantity_overflow.phpt
+++ b/Zend/tests/zend_ini/zend_ini_parse_uquantity_overflow.phpt
@@ -15,8 +15,8 @@
'No overflow 007' => ' -1',
'No overflow 008' => '-1 ',
'No overflow 009' => ' -1 ',
- 'Subject overflow 001' => base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10),
- 'Subject overflow 002' => '-'.base_convert(str_repeat('1', PHP_INT_SIZE*8+1), 2, 10),
+ 'Subject overflow 001' => PHP_INT_MAX.'0',
+ 'Subject overflow 002' => PHP_INT_MIN.'0',
'Subject overflow 003' => strval(PHP_INT_MIN),
'Subject overflow 004' => '-2',
'Subject overflow 005' => '-1K',
diff --git a/ext/standard/math.c b/ext/standard/math.c
index 1498a1efc0b..e13f153f63e 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -899,6 +899,7 @@ PHPAPI void _php_math_basetozval(zend_string *str, int base, zval *ret)
num = num * base + c;
break;
} else {
+ zend_error(E_NOTICE, "Input number is larger than PHP_INT_MAX, precision has been lost in conversion");
fnum = (double)num;
mode = 1;
}
diff --git a/ext/standard/tests/math/base_convert_overflow.phpt b/ext/standard/tests/math/base_convert_overflow.phpt
new file mode 100644
index 00000000000..0f74bdc76a6
--- /dev/null
+++ b/ext/standard/tests/math/base_convert_overflow.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test base_convert() - overflow test
+--FILE--
+<?php
+var_dump(base_convert('fffffffffffffffff', 16, 15));
+?>
+--EXPECTF--
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
+string(18) "2ee03c32ad644bd1e1"
\ No newline at end of file
diff --git a/ext/standard/tests/math/bindec_basic.phpt b/ext/standard/tests/math/bindec_basic.phpt
index 7640171fe61..d1197ed1645 100644
--- a/ext/standard/tests/math/bindec_basic.phpt
+++ b/ext/standard/tests/math/bindec_basic.phpt
@@ -50,6 +50,8 @@
int(455)
int(224)
int(2147483647)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(2147483648)
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
diff --git a/ext/standard/tests/math/bindec_basiclong_64bit.phpt b/ext/standard/tests/math/bindec_basiclong_64bit.phpt
index b4f28a091db..eb648c7c535 100644
--- a/ext/standard/tests/math/bindec_basiclong_64bit.phpt
+++ b/ext/standard/tests/math/bindec_basiclong_64bit.phpt
@@ -30,18 +30,24 @@
}
?>
---EXPECT--
+--EXPECTF--
--- testing: 0111111111111111111111111111111111111111111111111111111111111111 ---
int(9223372036854775807)
--- testing: 1111111111111111111111111111111111111111111111111111111111111111 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(1.8446744073709552E+19)
--- testing: 01111111111111111111111111111111 ---
int(2147483647)
--- testing: 11111111111111111111111111111111 ---
int(4294967295)
--- testing: 01111111111111111111111111111111111111111111111111111111111111111 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(1.8446744073709552E+19)
--- testing: 11111111111111111111111111111111111111111111111111111111111111111 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(3.6893488147419103E+19)
--- testing: 011111111111111111111111111111111 ---
int(4294967295)
diff --git a/ext/standard/tests/math/gh22395.phpt b/ext/standard/tests/math/gh22395.phpt
index 73c2c66da19..6ccbb44d669 100644
--- a/ext/standard/tests/math/gh22395.phpt
+++ b/ext/standard/tests/math/gh22395.phpt
@@ -6,6 +6,7 @@
var_dump(strlen($result));
var_dump(substr($result, 0, 13));
?>
---EXPECT--
+--EXPECTF--
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
int(78)
string(13) "4b61b5e0639ff"
diff --git a/ext/standard/tests/math/hexdec.phpt b/ext/standard/tests/math/hexdec.phpt
index ba09875efc3..1f8b57d83fd 100644
--- a/ext/standard/tests/math/hexdec.phpt
+++ b/ext/standard/tests/math/hexdec.phpt
@@ -10,8 +10,8 @@
var_dump(hexdec("q12345"));
var_dump(hexdec("12345+?!"));
var_dump(hexdec("12345q"));
-var_dump((float)hexdec("1234500001"));
-var_dump((float)hexdec("17fffffff"));
+var_dump(hexdec("12345678901234567"));
+var_dump(hexdec("17fffffffffffffff"));
?>
--EXPECTF--
@@ -26,5 +26,9 @@
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
int(74565)
-float(78187069441)
-float(6442450943)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
+float(2.0988295476557332E+19)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
+float(2.7670116110564327E+19)
diff --git a/ext/standard/tests/math/hexdec_basic.phpt b/ext/standard/tests/math/hexdec_basic.phpt
index 2f06b9650ae..f1fd76778bf 100644
--- a/ext/standard/tests/math/hexdec_basic.phpt
+++ b/ext/standard/tests/math/hexdec_basic.phpt
@@ -32,11 +32,17 @@
--EXPECTF--
int(18433668)
int(126895953)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(142929835591)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(142929835592)
int(1194684)
int(7904751)
int(2147483647)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(2147483648)
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
diff --git a/ext/standard/tests/math/hexdec_basiclong_64bit.phpt b/ext/standard/tests/math/hexdec_basiclong_64bit.phpt
index af0b448cac0..7475d982004 100644
--- a/ext/standard/tests/math/hexdec_basiclong_64bit.phpt
+++ b/ext/standard/tests/math/hexdec_basiclong_64bit.phpt
@@ -30,18 +30,24 @@
}
?>
---EXPECT--
+--EXPECTF--
--- testing: 7fffffffffffffff ---
int(9223372036854775807)
--- testing: ffffffffffffffff ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(1.8446744073709552E+19)
--- testing: 7fffffff ---
int(2147483647)
--- testing: ffffffff ---
int(4294967295)
--- testing: 7ffffffffffffffff ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(1.4757395258967641E+20)
--- testing: ffffffffffffffffff ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(4.722366482869645E+21)
--- testing: 7ffffffff ---
int(34359738367)
diff --git a/ext/standard/tests/math/hexdec_variation1.phpt b/ext/standard/tests/math/hexdec_variation1.phpt
index 65ebbe347b9..cf0d4e81411 100644
--- a/ext/standard/tests/math/hexdec_variation1.phpt
+++ b/ext/standard/tests/math/hexdec_variation1.phpt
@@ -86,9 +86,13 @@
int(9029)
-- Iteration 5 --
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(285960729237)
-- Iteration 6 --
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(285960729238)
-- Iteration 7 --
@@ -102,10 +106,14 @@
int(261)
-- Iteration 9 --
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(20015998341120)
-- Iteration 10 --
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
+
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
float(1250999896553)
diff --git a/ext/standard/tests/math/octdec_basic.phpt b/ext/standard/tests/math/octdec_basic.phpt
index 4c3ffc8b8a9..935cb23e1d3 100644
--- a/ext/standard/tests/math/octdec_basic.phpt
+++ b/ext/standard/tests/math/octdec_basic.phpt
@@ -46,6 +46,8 @@
int(342391)
int(375)
int(2147483647)
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(2147483648)
Deprecated: Invalid characters passed for attempted conversion, these have been ignored in %s on line %d
diff --git a/ext/standard/tests/math/octdec_basiclong_64bit.phpt b/ext/standard/tests/math/octdec_basiclong_64bit.phpt
index 06e0dd3929d..4637893d347 100644
--- a/ext/standard/tests/math/octdec_basiclong_64bit.phpt
+++ b/ext/standard/tests/math/octdec_basiclong_64bit.phpt
@@ -30,18 +30,24 @@
}
?>
---EXPECT--
+--EXPECTF--
--- testing: 777777777777777777777 ---
int(9223372036854775807)
--- testing: 1777777777777777777777 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(1.8446744073709552E+19)
--- testing: 17777777777 ---
int(2147483647)
--- testing: 37777777777 ---
int(4294967295)
--- testing: 377777777777777777777777 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(2.3611832414348226E+21)
--- testing: 17777777777777777777777777 ---
+
+Notice: Input number is larger than PHP_INT_MAX, precision has been lost in conversion in %s on line %d
float(7.555786372591432E+22)
--- testing: 377777777777 ---
int(34359738367)