[php-src] Issue #24437: JIT: tracing JIT gives wrong sum for `$a[0] += $i + 1` on an array parameter in a loop
| From: | waroad | 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.