Skip to content

Commit ab595c0

Browse files
committed
Fix GH-16411: gmp_export() can cause overflow
We need not only to avoid the signed overflow while calculating `bits_per_word` (reported issue), but also the unsigned overflow when calculating `count`. While the former has a fixed threshold, the latter does not, since it also depends on the size in base 2. Thus we use a somewhat unconventional error message. Closes GH-16418.
1 parent 1d94fb8 commit ab595c0

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ PHP NEWS
3838
- GMP:
3939
. Fixed floating point exception bug with gmp_pow when using
4040
large exposant values. (David Carlier).
41+
. Fixed bug GH-16411 (gmp_export() can cause overflow). (cmb)
4142

4243
- MBstring:
4344
. Fixed bug GH-16361 (mb_substr overflow on start/length arguments).

ext/gmp/gmp.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,8 +1002,14 @@ ZEND_FUNCTION(gmp_export)
10021002
if (mpz_sgn(gmpnumber) == 0) {
10031003
RETVAL_EMPTY_STRING();
10041004
} else {
1005-
size_t bits_per_word = size * 8;
1006-
size_t count = (mpz_sizeinbase(gmpnumber, 2) + bits_per_word - 1) / bits_per_word;
1005+
ZEND_ASSERT(size > 0);
1006+
size_t size_in_base_2 = mpz_sizeinbase(gmpnumber, 2);
1007+
if (size > ZEND_LONG_MAX / 4 || size_in_base_2 > SIZE_MAX - (size_t) size * 8 + 1) {
1008+
zend_argument_value_error(2, "is too large for argument #1 ($num)");
1009+
RETURN_THROWS();
1010+
}
1011+
size_t bits_per_word = (size_t) size * 8;
1012+
size_t count = (size_in_base_2 + bits_per_word - 1) / bits_per_word;
10071013

10081014
zend_string *out_string = zend_string_safe_alloc(count, size, 0, 0);
10091015
mpz_export(ZSTR_VAL(out_string), NULL, order, size, endian, 0, gmpnumber);

ext/gmp/tests/gh16411.phpt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
--TEST--
2+
GH-16411 (gmp_export() can cause overflow)
3+
--EXTENSIONS--
4+
gmp
5+
--FILE--
6+
<?php
7+
gmp_export("-9223372036854775808", PHP_INT_MAX, PHP_INT_MIN);
8+
?>
9+
--EXPECTF--
10+
Fatal error: Uncaught ValueError: gmp_export(): Argument #2 ($word_size) is too large for argument #1 ($num) in %s:%d
11+
%A

0 commit comments

Comments
 (0)