[php-src] PR #24394: JIT: Fix SIGFPE on LONG_MIN % -1 with a constant divisor
| From: | waroad | Date: | Sun, 18 Oct 2026 00:20:30 +0000 |
| Subject: | [php-src] PR #24394: JIT: Fix SIGFPE on LONG_MIN % -1 with a constant divisor | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39527@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24394
Author: waroad
With the function JIT,
$x % -1 with a literal -1 divisor crashes with
SIGFPE when $x is PHP_INT_MIN, where the interpreter returns
int(0). The cause is in zend_jit_long_math_helper(): for
ZEND_MOD with a constant divisor, only 0 and powers of two get special handling. Every
other constant, -1 included, becomes a plain ir_MOD_L(), i.e. an idiv by
-1, and that traps on ZEND_LONG_MIN. The non-constant branch just below already guards
against this.
The fix adds an op2_lval == -1 case to the constant branch that sets the result to the
constant 0, the same thing mod_function() does. For the test, I added a
modNeg1(PHP_INT_MIN) call to ext/opcache/tests/jit/mod_002.phpt, which
already covers constant divisors including -1. On PHP-8.4 (debug + ASan build), that
test and the reproducer from the issue both die with an FPE under opcache.jit=function
without the fix, and print int(0) with it. All of ext/opcache/tests/jit
passes under both the function and the tracing JIT.
It targets PHP-8.4, the lowest branch still taking bug fixes; the issue also reproduces on master.
Fixes #24390.
Found with an LLM-based testing tool; I wrote this fix with help from Claude and reviewed it myself.