Skip to content

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

Open

Description

@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
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 c65321c and it still reproduces at 9253b03. 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
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.

Activity

  1. ndossche commented on Oct 19, 2026

    @ndossche
    Member

    Indeed similar to #24387, feel free to open a PR!

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions