diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index ef06d0fda30c..c9700f331bfb 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -48,6 +48,7 @@ #define GMP_LITTLE_ENDIAN (1 << 2) #define GMP_BIG_ENDIAN (1 << 3) #define GMP_NATIVE_ENDIAN (1 << 4) +#define GMP_POW_MAX_EXP 1000000L #include "gmp_arginfo.h" @@ -1125,14 +1126,22 @@ ZEND_FUNCTION(gmp_pow) mpz_ptr gmpnum_result; mpz_ptr gmpnum_base; zend_long exp; + size_t bits; ZEND_PARSE_PARAMETERS_START(2, 2) GMP_Z_PARAM_INTO_MPZ_PTR(gmpnum_base) Z_PARAM_LONG(exp) ZEND_PARSE_PARAMETERS_END(); - if (exp < 0 || exp > ULONG_MAX) { - zend_argument_value_error(2, "must be between 0 and %lu", ULONG_MAX); + if (exp < 0) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + RETURN_THROWS(); + } + + bits = mpz_sizeinbase(gmpnum_base, 2); + + if (exp < 0 || exp > (SIZE_MAX - 5) / bits) { + zend_argument_value_error(2, "results in a value that exceeds the supported size"); RETURN_THROWS(); } diff --git a/ext/gmp/tests/gh22351.phpt b/ext/gmp/tests/gh22351.phpt new file mode 100644 index 000000000000..d5aa0cec8fa9 --- /dev/null +++ b/ext/gmp/tests/gh22351.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-22351: gmp_pow with PHP_INT_MAX should not crash +--EXTENSIONS-- +gmp +--FILE-- +getMessage() . PHP_EOL; +} + +echo "Done\n"; +?> +--EXPECTF-- +Testing gmp_pow overflow safety +ValueError: gmp_pow(): Argument #2 ($exponent) results in a value that exceeds the supported size +Done diff --git a/ext/gmp/tests/gmp_pow.phpt b/ext/gmp/tests/gmp_pow.phpt index 36d0d16d8ccc..6a61cf43a617 100644 --- a/ext/gmp/tests/gmp_pow.phpt +++ b/ext/gmp/tests/gmp_pow.phpt @@ -49,11 +49,11 @@ string(4) "1024" string(5) "-2048" string(4) "1024" string(1) "1" -gmp_pow(): Argument #2 ($exponent) must be between 0 and %d +gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 string(4) "1024" string(14) "10240000000000" string(17) "97656250000000000" -gmp_pow(): Argument #2 ($exponent) must be between 0 and %d +gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 string(14) "10240000000000" string(14) "10240000000000" gmp_pow(): Argument #2 ($exponent) must be of type int, array given