[php-src] Issue #24801: JIT: SIGFPE in ir_fold MUL_OV constant folding for `$x = -1; $x *= PHP_INT_MIN` in a hot loop

From: Date: Tue, 27 Oct 2026 23:24:16 +0000
Subject: [php-src] Issue #24801: JIT: SIGFPE in ir_fold MUL_OV constant folding for `$x = -1; $x *= PHP_INT_MIN` in a hot loop
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253255@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24801 Author: waroad 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. ```php <?php for ($k = 0; $k < 200; $k++) { $x = -1; $x *= PHP_INT_MIN; } var_dump($x); ``` ``` php -n -d opcache.enable_cli=1 -d opcache.file_update_protection=0 -d opcache.jit=tracing -d opcache.jit_buffer_size=64M red.php ``` 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 c65321c70f7de5f4a4f810f1d23112374d92d1a7 (UBSan report and release SIGFPE as above). It still reproduces at 1b1aa3578034: 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.

« previous php.bugs (#253255) next »