From 45140e527f4eabf167e857f46ee9e0851ef6ac8b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 25 Nov 2024 18:11:59 +0000 Subject: [PATCH 1/3] Revert "ext/gmp: gmp_pow fix FPE with large values." This reverts commit e0a0e216a909dc4ee4ea7c113a5f41d49525f02e. --- NEWS | 2 - ext/gmp/gmp.c | 38 +++++++++------ ext/gmp/tests/gmp_pow.phpt | 2 - ext/gmp/tests/gmp_pow_32bits.phpt | 77 ------------------------------- ext/gmp/tests/gmp_pow_fpe.phpt | 35 ++++---------- 5 files changed, 35 insertions(+), 119 deletions(-) delete mode 100644 ext/gmp/tests/gmp_pow_32bits.phpt diff --git a/NEWS b/NEWS index d4dea493bca0a..d4e9d62944845 100644 --- a/NEWS +++ b/NEWS @@ -134,8 +134,6 @@ PHP NEWS . Fixed bug GH-16411 (gmp_export() can cause overflow). (cmb) . Fixed bug GH-16501 (gmp_random_bits() can cause overflow). (David Carlier) - . Fixed gmp_pow() overflow bug with large base/exponents. - (David Carlier) . Fixed segfaults and other issues related to operator overloading with GMP objects. (Girgias) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index c9603c8fb21e8..fc5464e90542d 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1350,27 +1350,39 @@ ZEND_FUNCTION(gmp_pow) RETURN_THROWS(); } - double powmax = log((double)ZEND_LONG_MAX); - if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { INIT_GMP_RETVAL(gmpnum_result); - if ((log(Z_LVAL_P(base_arg)) * exp) > powmax) { - zend_value_error("base and exponent overflow"); - RETURN_THROWS(); + if (exp >= INT_MAX) { + mpz_t base_num, exp_num, mod; + mpz_init(base_num); + mpz_init(exp_num); + mpz_init(mod); + mpz_set_si(base_num, Z_LVAL_P(base_arg)); + mpz_set_si(exp_num, exp); + mpz_set_ui(mod, UINT_MAX); + mpz_powm(gmpnum_result, base_num, exp_num, mod); + mpz_clear(mod); + mpz_clear(exp_num); + mpz_clear(base_num); + } else { + mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); } - mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); } else { mpz_ptr gmpnum_base; - zend_ulong gmpnum; FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1); INIT_GMP_RETVAL(gmpnum_result); - gmpnum = mpz_get_ui(gmpnum_base); - if ((log(gmpnum) * exp) > powmax) { - FREE_GMP_TEMP(temp_base); - zend_value_error("base and exponent overflow"); - RETURN_THROWS(); + if (exp >= INT_MAX) { + mpz_t exp_num, mod; + mpz_init(exp_num); + mpz_init(mod); + mpz_set_si(exp_num, exp); + mpz_set_ui(mod, UINT_MAX); + mpz_powm(gmpnum_result, gmpnum_base, exp_num, mod); + mpz_clear(mod); + mpz_clear(exp_num); + } else { + mpz_pow_ui(gmpnum_result, gmpnum_base, exp); } - mpz_pow_ui(gmpnum_result, gmpnum_base, exp); FREE_GMP_TEMP(temp_base); } } diff --git a/ext/gmp/tests/gmp_pow.phpt b/ext/gmp/tests/gmp_pow.phpt index 1d77bd5e96c80..f42e44e31abed 100644 --- a/ext/gmp/tests/gmp_pow.phpt +++ b/ext/gmp/tests/gmp_pow.phpt @@ -2,8 +2,6 @@ gmp_pow() basic tests --EXTENSIONS-- gmp ---SKIPIF-- - --FILE-- ---FILE-- -getMessage() . "\n"; -} -var_dump(gmp_strval(gmp_pow("-2",10))); -try { - gmp_pow(20,10); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} -try { - gmp_pow(50,10); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} -try { - gmp_pow(50,-5); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} -try { - $n = gmp_init("20"); - gmp_pow($n,10); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} -try { - $n = gmp_init("-20"); - gmp_pow($n,10); -} catch (ValueError $exception) { - echo $exception->getMessage() . "\n"; -} -try { - var_dump(gmp_pow(2,array())); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} - -try { - var_dump(gmp_pow(array(),10)); -} catch (\TypeError $e) { - echo $e->getMessage() . \PHP_EOL; -} - -echo "Done\n"; -?> ---EXPECT-- -string(4) "1024" -string(4) "1024" -string(5) "-2048" -string(4) "1024" -string(1) "1" -gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 -string(4) "1024" -base and exponent overflow -base and exponent overflow -gmp_pow(): Argument #2 ($exponent) must be greater than or equal to 0 -base and exponent overflow -base and exponent overflow -gmp_pow(): Argument #2 ($exponent) must be of type int, array given -gmp_pow(): Argument #1 ($num) must be of type GMP|string|int, array given -Done diff --git a/ext/gmp/tests/gmp_pow_fpe.phpt b/ext/gmp/tests/gmp_pow_fpe.phpt index 248922e80514d..d564853799c8d 100644 --- a/ext/gmp/tests/gmp_pow_fpe.phpt +++ b/ext/gmp/tests/gmp_pow_fpe.phpt @@ -6,30 +6,15 @@ gmp getMessage() . PHP_EOL; -} -try { - gmp_pow(256, PHP_INT_MAX); -} catch (\ValueError $e) { - echo $e->getMessage() . PHP_EOL; -} - -try { - gmp_pow(gmp_add(gmp_mul(gmp_init(PHP_INT_MAX), gmp_init(PHP_INT_MAX)), 3), 256); -} catch (\ValueError $e) { - echo $e->getMessage() . PHP_EOL; -} -try { - gmp_pow(gmp_init(PHP_INT_MAX), 256); -} catch (\ValueError $e) { - echo $e->getMessage(); -} +var_dump(gmp_pow($g, PHP_INT_MAX)); +var_dump(gmp_pow(256, PHP_INT_MAX)); ?> --EXPECTF-- -base and exponent overflow -base and exponent overflow -base and exponent overflow -base and exponent overflow +object(GMP)#2 (1) { + ["num"]=> + string(%d) "%s" +} +object(GMP)#2 (1) { + ["num"]=> + string(%d) "%s" +} From 7e8d6f941c18d7f753755d7a24637640cb88c11b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 25 Nov 2024 18:12:22 +0000 Subject: [PATCH 2/3] Revert "ext/gmp: gmp_pow fix FPE with large values." This reverts commit d70b7811b0248a36b06d70a04e350801a1fede8e. --- NEWS | 2 -- ext/gmp/gmp.c | 29 ++--------------------------- ext/gmp/tests/gmp_pow_fpe.phpt | 20 -------------------- 3 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 ext/gmp/tests/gmp_pow_fpe.phpt diff --git a/NEWS b/NEWS index d4e9d62944845..65c8f8cae595a 100644 --- a/NEWS +++ b/NEWS @@ -129,8 +129,6 @@ PHP NEWS (nielsdos) - 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) . Fixed bug GH-16501 (gmp_random_bits() can cause overflow). (David Carlier) diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index fc5464e90542d..f31d6ab810232 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -1352,37 +1352,12 @@ ZEND_FUNCTION(gmp_pow) if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 0) { INIT_GMP_RETVAL(gmpnum_result); - if (exp >= INT_MAX) { - mpz_t base_num, exp_num, mod; - mpz_init(base_num); - mpz_init(exp_num); - mpz_init(mod); - mpz_set_si(base_num, Z_LVAL_P(base_arg)); - mpz_set_si(exp_num, exp); - mpz_set_ui(mod, UINT_MAX); - mpz_powm(gmpnum_result, base_num, exp_num, mod); - mpz_clear(mod); - mpz_clear(exp_num); - mpz_clear(base_num); - } else { - mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); - } + mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); } else { mpz_ptr gmpnum_base; FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1); INIT_GMP_RETVAL(gmpnum_result); - if (exp >= INT_MAX) { - mpz_t exp_num, mod; - mpz_init(exp_num); - mpz_init(mod); - mpz_set_si(exp_num, exp); - mpz_set_ui(mod, UINT_MAX); - mpz_powm(gmpnum_result, gmpnum_base, exp_num, mod); - mpz_clear(mod); - mpz_clear(exp_num); - } else { - mpz_pow_ui(gmpnum_result, gmpnum_base, exp); - } + mpz_pow_ui(gmpnum_result, gmpnum_base, exp); FREE_GMP_TEMP(temp_base); } } diff --git a/ext/gmp/tests/gmp_pow_fpe.phpt b/ext/gmp/tests/gmp_pow_fpe.phpt deleted file mode 100644 index d564853799c8d..0000000000000 --- a/ext/gmp/tests/gmp_pow_fpe.phpt +++ /dev/null @@ -1,20 +0,0 @@ ---TEST-- -gmp_pow() floating point exception ---EXTENSIONS-- -gmp ---FILE-- - ---EXPECTF-- -object(GMP)#2 (1) { - ["num"]=> - string(%d) "%s" -} -object(GMP)#2 (1) { - ["num"]=> - string(%d) "%s" -} From 5fd53a8b93e167b990be331838cea32c6d4c0cac Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 27 Nov 2024 19:53:09 +0000 Subject: [PATCH 3/3] [skip ci] NEWS --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 65c8f8cae595a..5dbe5571c4a2b 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,10 @@ PHP NEWS - GD: . Fixed GH-16776 (imagecreatefromstring overflow). (David Carlier) +- GMP: + . Revert gmp_pow() overly restrictive overflow checks. + (David Carlier) + - Hash: . Fixed GH-16711: Segfault in mhash(). (Girgias)