Skip to content

Commit

Permalink
Fix phpGH-16411: gmp_export() can cause overflow
Browse files Browse the repository at this point in the history
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 phpGH-16418.
  • Loading branch information
cmb69 committed Oct 15, 2024
1 parent 1d94fb8 commit ab595c0
Showing 3 changed files with 20 additions and 2 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ PHP NEWS
- GMP:
. Fixed floating point exception bug with gmp_pow when using
large exposant values. (David Carlier).
. Fixed bug GH-16411 (gmp_export() can cause overflow). (cmb)

- MBstring:
. Fixed bug GH-16361 (mb_substr overflow on start/length arguments).
10 changes: 8 additions & 2 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
@@ -1002,8 +1002,14 @@ ZEND_FUNCTION(gmp_export)
if (mpz_sgn(gmpnumber) == 0) {
RETVAL_EMPTY_STRING();
} else {
size_t bits_per_word = size * 8;
size_t count = (mpz_sizeinbase(gmpnumber, 2) + bits_per_word - 1) / bits_per_word;
ZEND_ASSERT(size > 0);
size_t size_in_base_2 = mpz_sizeinbase(gmpnumber, 2);
if (size > ZEND_LONG_MAX / 4 || size_in_base_2 > SIZE_MAX - (size_t) size * 8 + 1) {
zend_argument_value_error(2, "is too large for argument #1 ($num)");
RETURN_THROWS();
}
size_t bits_per_word = (size_t) size * 8;
size_t count = (size_in_base_2 + bits_per_word - 1) / bits_per_word;

zend_string *out_string = zend_string_safe_alloc(count, size, 0, 0);
mpz_export(ZSTR_VAL(out_string), NULL, order, size, endian, 0, gmpnumber);
11 changes: 11 additions & 0 deletions ext/gmp/tests/gh16411.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--TEST--
GH-16411 (gmp_export() can cause overflow)
--EXTENSIONS--
gmp
--FILE--
<?php
gmp_export("-9223372036854775808", PHP_INT_MAX, PHP_INT_MIN);
?>
--EXPECTF--
Fatal error: Uncaught ValueError: gmp_export(): Argument #2 ($word_size) is too large for argument #1 ($num) in %s:%d
%A

0 comments on commit ab595c0

Please sign in to comment.