Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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();
}

Expand Down
22 changes: 22 additions & 0 deletions ext/gmp/tests/gh22351.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
GH-22351: gmp_pow with PHP_INT_MAX should not crash
--EXTENSIONS--
gmp
--FILE--
<?php

echo "Testing gmp_pow overflow safety\n";

try {
$r = gmp_pow(2, PHP_INT_MAX);
var_dump($r);
} catch (ValueError $e) {
echo "ValueError: " . $e->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
4 changes: 2 additions & 2 deletions ext/gmp/tests/gmp_pow.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading