You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ext/gmp: operator-overloaded ** and << crash with SIGFPE on large operand (shift_operator_helper unbounded) #24713
GMP object operator overloading for ** (pow) and << (left shift) crashes the PHP process with an uncatchable SIGFPE when given a sufficiently large second operand. This is the same underlying GMP overflow-detection abort as GH-16384 (gmp_pow() function-call form), but reached through a different, separate code path: shift_operator_helper() in ext/gmp/gmp.c, which backs the operator-overloaded forms rather than the gmp_pow()/gmp_mul() function calls.
<?phpvar_dump(gmp_init(2) ** 400000000000);
<?phpvar_dump(gmp_init(2) << 400000000000);
Either script crashes the process immediately with no catchable PHP-level error.
Root cause
In shift_operator_helper():
if (!have_shift_ui) {
if (shift<0||shift>ULONG_MAX) {
gmp_shift_operator_range_error(opcode);
returnFAILURE;
}
shift_ui= (gmp_ulong) shift;
}
shift is a zend_long (signed 64-bit), so shift > ULONG_MAX can never be true — a signed 64-bit value can never reach the max of an unsigned 64-bit type. The effective upper bound is therefore nonexistent. This function is used for **, <<, and >> via gmp_do_operation_ex():
A huge shift reaches mpz_pow_ui/mpz_mul_2exp directly. Both need to allocate a result whose size scales with shift itself, and GMP's own internal size bookkeeping detects the resulting overflow and raises SIGFPE via its internal exception path — uncatchable by PHP. (>>/mpz_fdiv_q_2exp doesn't hit this, since a huge right-shift just truncates to 0 in roughly constant time.)
GH-16384 is about ZEND_FUNCTION(gmp_pow) — the function-call form gmp_pow($base, $exp) — which has its own, separate copy of essentially the same broken bound check at a different line. This report is about the operator-overloaded form ($base ** $exp, $base << $n), a structurally distinct code path (shift_operator_helper) that was never touched by any prior fix for GH-16384.
Affected versions
Confirmed on current master. Also affects PHP-8.3/PHP-8.4 — the equivalent code on those branches has no upper-bound check at all (just if (shift < 0)), so the same mpz_pow_ui/mpz_mul_2exp call is reached with an attacker-controlled huge value there too.
PHP Version
master (and PHP-8.3, PHP-8.4)
Operating System
Linux (reproduced in a clean Ubuntu 24.04 container; not OS-specific)
Activity
lazerg commentedon Oct 26, 2026
This looks like the same GMP problem as in #22351 (comment). Girgias said there that PHP cannot fix it until GMP can handle these errors.
kunwaratulhax0r commentedon Oct 26, 2026
Hi @lazerg, thanks for the update. Can I close this as a known issue?
lazerg commentedon Oct 26, 2026
Yes.