From 9ca68e037ce04a9ed639cbe8fb493cdc21a97e05 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 19 Oct 2024 06:01:32 +0100 Subject: [PATCH] Fix GH-16501: gmp_random_bits overflow. we do the same calculation in advance as mpz_realloc overflow check to avoid abort. close GH-16503 --- NEWS | 2 ++ ext/gmp/gmp.c | 12 +++++++++--- ext/gmp/tests/gh16501.phpt | 14 ++++++++++++++ ext/gmp/tests/gmp_random_bits.phpt | 6 +++--- 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 ext/gmp/tests/gh16501.phpt diff --git a/NEWS b/NEWS index 404b3756685d0..b96cdd8223625 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,8 @@ PHP NEWS . 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) + . Fixed bug GH-16501 (gmp_random_bits() can cause overflow). + (David Carlier) - 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 bae141b574af6..ba62b37ad2c8a 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1803,15 +1803,21 @@ ZEND_FUNCTION(gmp_random_bits) RETURN_THROWS(); } - if (bits <= 0) { - zend_argument_value_error(1, "must be greater than or equal to 1"); +#if SIZEOF_SIZE_T == 4 + const zend_long maxbits = ULONG_MAX / GMP_NUMB_BITS; +#else + const zend_long maxbits = INT_MAX; +#endif + + if (bits <= 0 || bits > maxbits) { + zend_argument_value_error(1, "must be between 1 and " ZEND_LONG_FMT, maxbits); RETURN_THROWS(); } INIT_GMP_RETVAL(gmpnum_result); gmp_init_random(); - mpz_urandomb(gmpnum_result, GMPG(rand_state), bits); + mpz_urandomb(gmpnum_result, GMPG(rand_state), (mp_bitcnt_t)bits); } /* }}} */ diff --git a/ext/gmp/tests/gh16501.phpt b/ext/gmp/tests/gh16501.phpt new file mode 100644 index 0000000000000..325be85d1917e --- /dev/null +++ b/ext/gmp/tests/gh16501.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-16501 (gmp_random_bits overflow) +--EXTENSIONS-- +gmp +--FILE-- +getMessage(); +} +?> +--EXPECTF-- +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d diff --git a/ext/gmp/tests/gmp_random_bits.phpt b/ext/gmp/tests/gmp_random_bits.phpt index 3dbfc097d28d5..4e7f337983891 100644 --- a/ext/gmp/tests/gmp_random_bits.phpt +++ b/ext/gmp/tests/gmp_random_bits.phpt @@ -40,7 +40,7 @@ while (1) { echo "Done\n"; ?> ---EXPECT-- -gmp_random_bits(): Argument #1 ($bits) must be greater than or equal to 1 -gmp_random_bits(): Argument #1 ($bits) must be greater than or equal to 1 +--EXPECTF-- +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d +gmp_random_bits(): Argument #1 ($bits) must be between 1 and %d Done