From 42a4a97e591b5988909a94f8898d79eeca026bb1 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Wed, 17 Jun 2026 11:33:58 +0530 Subject: [PATCH 1/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent --- ext/gmp/gmp.c | 5 +++-- ext/gmp/tests/gh22351.phpt | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 ext/gmp/tests/gh22351.phpt diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index ef06d0fda30c..9e356c85f240 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" @@ -1131,8 +1132,8 @@ ZEND_FUNCTION(gmp_pow) 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 || exp > GMP_POW_MAX_EXP) { + zend_argument_value_error(2, "must be between 0 and %lu", GMP_POW_MAX_EXP); RETURN_THROWS(); } diff --git a/ext/gmp/tests/gh22351.phpt b/ext/gmp/tests/gh22351.phpt new file mode 100644 index 000000000000..5b1e345a1609 --- /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) must be between 0 and 1000000 +Done \ No newline at end of file From 2223bc6d491d230e1a4c1cdf8e5b617e27531f28 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Wed, 17 Jun 2026 11:34:40 +0530 Subject: [PATCH 2/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent --- ext/gmp/tests/gh22351.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/gmp/tests/gh22351.phpt b/ext/gmp/tests/gh22351.phpt index 5b1e345a1609..b1b8e08100ac 100644 --- a/ext/gmp/tests/gh22351.phpt +++ b/ext/gmp/tests/gh22351.phpt @@ -19,4 +19,4 @@ echo "Done\n"; --EXPECTF-- Testing gmp_pow overflow safety ValueError: gmp_pow(): Argument #2 ($exponent) must be between 0 and 1000000 -Done \ No newline at end of file +Done From 666fe1678dcf9dfef67af3e274fb660e4e956540 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Thu, 18 Jun 2026 08:58:02 +0530 Subject: [PATCH 3/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent --- ext/gmp/gmp.c | 12 ++++++++++-- ext/gmp/tests/gh22351.phpt | 2 +- ext/gmp/tests/gmp_pow.phpt | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index 9e356c85f240..c9700f331bfb 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1126,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 > GMP_POW_MAX_EXP) { - zend_argument_value_error(2, "must be between 0 and %lu", GMP_POW_MAX_EXP); + 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 index b1b8e08100ac..d5aa0cec8fa9 100644 --- a/ext/gmp/tests/gh22351.phpt +++ b/ext/gmp/tests/gh22351.phpt @@ -18,5 +18,5 @@ echo "Done\n"; ?> --EXPECTF-- Testing gmp_pow overflow safety -ValueError: gmp_pow(): Argument #2 ($exponent) must be between 0 and 1000000 +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 From eaa5120e794ce965acd21f6b164e1092c8a96d88 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 20 Jun 2026 12:28:52 +0530 Subject: [PATCH 4/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent --- ext/gmp/gmp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index c9700f331bfb..df7b3eb247c5 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -48,7 +48,6 @@ #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" @@ -1140,7 +1139,7 @@ ZEND_FUNCTION(gmp_pow) bits = mpz_sizeinbase(gmpnum_base, 2); - if (exp < 0 || exp > (SIZE_MAX - 5) / bits) { + if (exp > (SIZE_MAX - 5) / bits) { zend_argument_value_error(2, "results in a value that exceeds the supported size"); RETURN_THROWS(); } From 47b430b95ddc0b49b6b34cb65f94c8689314a7b4 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 20 Jun 2026 17:44:01 +0530 Subject: [PATCH 5/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent - shift_operator_helper --- ext/gmp/gmp.c | 28 ++++++++++++++++++++++++++- ext/gmp/tests/gmp_overflow_llp64.phpt | 9 +++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index df7b3eb247c5..9bf2d65f2df2 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -365,11 +365,37 @@ static zend_result shift_operator_helper(gmp_binary_ui_op_t op, zval *return_val return FAILURE; } else { mpz_ptr gmpnum_op, gmpnum_result; - + size_t bits; + if (!gmp_zend_parse_arg_into_mpz_ex(op1, &gmpnum_op, 1, true)) { goto typeof_op_failure; } + bits = mpz_sizeinbase(gmpnum_op, 2); + if (bits == 0) { + bits = 1; + } + + if (opcode == ZEND_POW) { + if ((size_t) shift > (SIZE_MAX - 5) / bits) { + zend_value_error( + "exponent results in a value that exceeds the supported size" + ); + return FAILURE; + } + } + + if (opcode == ZEND_SL) { + size_t max_shift = ((size_t)INT_MAX * GMP_NUMB_BITS); + + if ((size_t) shift > max_shift) { + zend_value_error( + "shift count results in a value that exceeds the supported size" + ); + return FAILURE; + } + } + INIT_GMP_RETVAL(gmpnum_result); op(gmpnum_result, gmpnum_op, (gmp_ulong) shift); return SUCCESS; diff --git a/ext/gmp/tests/gmp_overflow_llp64.phpt b/ext/gmp/tests/gmp_overflow_llp64.phpt index ea242bc52155..5b99c85c0209 100644 --- a/ext/gmp/tests/gmp_overflow_llp64.phpt +++ b/ext/gmp/tests/gmp_overflow_llp64.phpt @@ -49,10 +49,7 @@ try { echo "Done\n"; ?> --EXPECTF-- -gmp_pow(): Argument #2 ($exponent) must be between 0 and %d -gmp_binomial(): Argument #2 ($k) must be between 0 and %d -gmp_root(): Argument #2 ($nth) must be between 1 and %d -gmp_rootrem(): Argument #2 ($nth) must be between 1 and %d -Shift must be between 0 and %d -Exponent must be between 0 and %d +gmp_pow(): Argument #2 ($exponent) results in a value that exceeds the supported size +shift count results in a value that exceeds the supported size +exponent results in a value that exceeds the supported size Done From d5ead31357b214fbe83d7de5fe43af8c7a693084 Mon Sep 17 00:00:00 2001 From: arshidkv12 Date: Sat, 20 Jun 2026 18:34:16 +0530 Subject: [PATCH 6/6] ext/gmp: Fix crash in gmp_pow with excessively large exponent - shift_operator_helper --- ext/gmp/tests/gmp_overflow_llp64.phpt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/gmp/tests/gmp_overflow_llp64.phpt b/ext/gmp/tests/gmp_overflow_llp64.phpt index 5b99c85c0209..7a9e0adeeb12 100644 --- a/ext/gmp/tests/gmp_overflow_llp64.phpt +++ b/ext/gmp/tests/gmp_overflow_llp64.phpt @@ -50,6 +50,9 @@ echo "Done\n"; ?> --EXPECTF-- gmp_pow(): Argument #2 ($exponent) results in a value that exceeds the supported size -shift count results in a value that exceeds the supported size -exponent results in a value that exceeds the supported size +gmp_binomial(): Argument #2 ($k) must be between 0 and %d +gmp_root(): Argument #2 ($nth) must be between 1 and %d +gmp_rootrem(): Argument #2 ($nth) must be between 1 and %d +Shift must be between 0 and %d +Exponent must be between 0 and %d Done