[php-src] PR #24451: JIT: Fix OP_DATA read from an unwritten slot in zend_jit_assign_dim_op()
| From: | waroad | Date: | Tue, 20 Oct 2026 03:17:21 +0000 |
| Subject: | [php-src] PR #24451: JIT: Fix OP_DATA read from an unwritten slot in zend_jit_assign_dim_op() | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39621@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24451
Author: waroad
In
zend_jit_assign_dim_op(), when the array element may be a reference, the cold branch
for typed references spills the OP_DATA register to its stack slot and then sets op3_addr =
real_addr;. That reassignment also applies to the code emitted after the branch, so the
normal +=/%=/... path then reads the right-hand operand from a stack slot
that is only written on the typed-reference path. With the tracing JIT, $a[0] += $i + 1
on an array parameter adds a stale value (prints int(3) instead of
int(6)), and the %= variant from the issue can divide by a stale zero and
dies with SIGFPE. A CV on the right ($a[0] += $i) is affected too, also with the
default JIT counters.
The fix passes real_addr to the helper call only, the same way
zend_jit_assign_op() already does for its typed reference branch, and leaves
op3_addr alone for the rest of the function.
The new test ext/opcache/tests/jit/gh24437.phpt covers the undefined-key case, an
element that is a reference, an element that is a typed reference, and the %= case.
Without the fix the first two cases print 3 and 13 instead of 6 and 16, and the %= case
crashes with an FPE; with it, the test passes. The reproducers from the issue now match
opcache.jit=off.
Here's the PR, as suggested. It is close to #24387: there a register wasn't loaded on all
paths around the typed reference check; here the stack slot is written only on the typed-reference
path but read on the normal one. zend_jit_assign_dim_op() already force-loads OP_DATA
before the reference check, so the change from #24387 isn't needed here.
Targets PHP-8.4, where I built and tested it (debug + ASan/UBSan build);
ext/opcache/tests/jit passes in tracing and function mode.
Fixes #24437.
Found with an LLM-based testing tool; I wrote this fix with help from Claude and reviewed it myself.