[php-src] Issue #24437: JIT: tracing JIT gives wrong sum for `$a[0] += $i + 1` on an array parameter in a loop

From: Date: Mon, 19 Oct 2026 13:57:46 +0000
Subject: [php-src] Issue #24437: JIT: tracing JIT gives wrong sum for `$a[0] += $i + 1` on an array parameter in a loop
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-253029@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/24437 Author: waroad With the tracing JIT, $a[0] += $i + 1 in a loop on an array parameter adds the wrong value, so the function returns 3 instead of 6. ```php <?php function f($a) { for ($i = 0; $i < 3; $i++) { @$a[0] += $i + 1; } return $a[0]; } var_dump(f([1 => 2])); ``` ``` php -n -d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.file_update_protection=0 -d opcache.jit_buffer_size=64M -d opcache.jit=tracing -d opcache.jit_hot_loop=1 -d opcache.jit_hot_func=1 -d opcache.jit_hot_return=1 -d opcache.jit_hot_side_exit=1 r06.php ``` Output: ``` int(3) ``` Expected int(6) (null + 1 + 2 + 3); that is what -d opcache.jit=off prints. Found at commit c65321c70f7de5f4a4f810f1d23112374d92d1a7 and it still reproduces at 9253b03bef3f. Both the checking build and the release build exit 0 and print int(3), with no diagnostic. Looks like zend_jit_assign_dim_op in ext/opcache/jit/zend_jit_ir.c: in the cold typed-reference branch, op3_addr = real_addr; rebinds OP_DATA (the register holding $i + 1) to its stack slot, but the spill to that slot only runs on the cold path, so the common path reads the addend from a slot that was not written. Using a separate local variable in that branch gives 6 here. PR #18392 touches the same function and may be related; not tested here. #24387 (for #24386) fixes a similar typed-reference problem in zend_jit_assign_op; with it applied this still prints int(3). Probably the same cause, with %=: with the same command on this file, the checking (ASAN) build stops with AddressSanitizer: FPE in JIT code instead of printing done as the interpreter does (release build not tried). The same local-variable change fixes it. ```php <?php function f($a) { for ($i = 0; $i < 3; $i++) { $a[2] %= $i + 1; $x = $a[0] %= 1; } } @f([]); echo "done\n"; ``` I can send a patch if that helps. Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.

« previous php.bugs (#253029) next »