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
JIT: SIGFPE in ir_fold MUL_OV constant folding for $x = -1; $x *= PHP_INT_MIN in a hot loop #24801
With the tracing JIT, compiling a trace that contains $x = -1; $x *= PHP_INT_MIN computes INT64_MIN / -1 inside the IR constant folder, which is undefined behaviour and crashes the release build with SIGFPE.
Release build: the process dies with SIGFPE (exit status 136) and prints nothing. A UBSan build (UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1) reports:
ext/opcache/jit/ir/ir_fold.h:1004:37: runtime error: division of -9223372036854775808 by -1 cannot be represented in type 'long int'
#0 ir_folding ext/opcache/jit/ir/ir_fold.h:1004
#1 ir_fold ext/opcache/jit/ir/ir.c:1305
#2 ir_fold2 ext/opcache/jit/ir/ir.c:1320
#3 zend_jit_math_long_long ext/opcache/jit/zend_jit_ir.c:5039
#4 zend_jit_math_helper ext/opcache/jit/zend_jit_ir.c:5382
I expected float(9.2233720368547758E+18), which is what -1 * PHP_INT_MIN evaluates to without the JIT, and no crash.
Found at commit c65321c (UBSan report and release SIGFPE as above). It still reproduces at 1b1aa35: the UBSan build reports the same division at ir_fold.h:1004, and the release build exits with SIGFPE (136).
Looks like the overflow check in IR_FOLD(MUL_OV(C_I64, C_I64)) in ext/opcache/jit/ir/ir_fold.h (res / op1_insn->val.i64 != op2_insn->val.i64) divides by -1 when res is INT64_MIN. It may need a -1 guard or __builtin_mul_overflow.
The trigger is a generated test case, not code from a real program.
Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.
Activity
ndossche commentedon Oct 28, 2026
This'll need a fix at https://github.com/dstogov/ir , would you like to PR something there?