diff --git a/NEWS b/NEWS index a05fdcf4b344d..c62a0c0745e43 100644 --- a/NEWS +++ b/NEWS @@ -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). diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 2b68d925099f8..bae141b574af6 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -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); diff --git a/ext/gmp/tests/gh16411.phpt b/ext/gmp/tests/gh16411.phpt new file mode 100644 index 0000000000000..798943002cfce --- /dev/null +++ b/ext/gmp/tests/gh16411.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-16411 (gmp_export() can cause overflow) +--EXTENSIONS-- +gmp +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught ValueError: gmp_export(): Argument #2 ($word_size) is too large for argument #1 ($num) in %s:%d +%A