Skip to content

JIT: Fix SIGFPE on LONG_MIN % -1 with a constant divisor - #24394

Closed
waroad wants to merge 1 commit into
php:PHP-8.4from
waroad:traj-s-20261017-005254-07-sigfpe-int-min-mod-minus-one-pr4
Closed

waroad wants to merge 1 commit into
php:PHP-8.4from
waroad:traj-s-20261017-005254-07-sigfpe-int-min-mod-minus-one-pr4

Conversation

@waroad

@waroad waroad commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

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.

@ndossche ndossche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants