Commit 0236667bd94 for php.net
commit 0236667bd941bec856ffb95e39f8f95b80c68edd
Author: David Carlier <devnexen@gmail.com>
Date: Sat Apr 18 07:17:48 2026 +0100
ext/gmp: gmp_fact() reject values larger than unsigned long.
close GH-21794
diff --git a/NEWS b/NEWS
index f5c9cfa7550..2000d5b4710 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,9 @@ PHP NEWS
. imagesetstyle()/imagefilter()/imagecrop() check array argument entries
types. (David Carlier)
+- GMP:
+ . gmp_fact() reject values larger than unsigned long. (David Carlier)
+
- Hash:
. Upgrade xxHash to 0.8.2. (timwolla)
diff --git a/UPGRADING b/UPGRADING
index 5e32a5418b5..10a63f6b03a 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -141,6 +141,10 @@ PHP 8.6 UPGRADE NOTES
5. Changed Functions
========================================
+- GMP:
+ . gmp_fact() now throws a ValueError() if $num does not fit into
+ a unsigned long.
+
- mysqli:
. The return structure of mysqli_get_charset() no longer contains
the undocumented "comment" element. The value of "charsetnr" is
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index cf6580e95e9..a2097458090 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -1092,8 +1092,10 @@ ZEND_FUNCTION(gmp_fact)
RETURN_THROWS();
}
- // TODO: Check that we don't an int that is larger than an unsigned long?
- // Could use mpz_fits_slong_p() if we revert to using mpz_get_si()
+ if (!mpz_fits_ulong_p(gmpnum)) {
+ zend_argument_value_error(1, "must be between 0 and %lu", ULONG_MAX);
+ RETURN_THROWS();
+ }
INIT_GMP_RETVAL(gmpnum_result);
mpz_fac_ui(gmpnum_result, mpz_get_ui(gmpnum));
diff --git a/ext/gmp/tests/gmp_fact_overflow.phpt b/ext/gmp/tests/gmp_fact_overflow.phpt
new file mode 100644
index 00000000000..2d22005818c
--- /dev/null
+++ b/ext/gmp/tests/gmp_fact_overflow.phpt
@@ -0,0 +1,25 @@
+--TEST--
+gmp_fact() rejects values larger than unsigned long
+--EXTENSIONS--
+gmp
+--FILE--
+<?php
+
+try {
+ var_dump(gmp_fact(gmp_pow(2, 100)));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
+
+try {
+ var_dump(gmp_fact(gmp_init("18446744073709551616")));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+gmp_fact(): Argument #1 ($num) must be between 0 and %d
+gmp_fact(): Argument #1 ($num) must be between 0 and %d
+Done