From 538b3c000a05fc50796be4d1f216411aa15d1d3e Mon Sep 17 00:00:00 2001 From: waroad Date: Mon, 19 Oct 2026 22:11:35 -0500 Subject: [PATCH] JIT: Fix OP_DATA read from an unwritten slot in zend_jit_assign_dim_op() The typed-reference branch spilled OP_DATA to its stack slot and then set op3_addr to that slot, so the code emitted after the branch also read OP_DATA from the slot, which is only written on the typed-reference path. Pass the slot to zend_jit_assign_op_to_typed_ref() only, as zend_jit_assign_op() does. Assisted-by: Claude --- ext/opcache/jit/zend_jit_ir.c | 5 +-- ext/opcache/tests/jit/gh24437.phpt | 50 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/jit/gh24437.phpt diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 947e87f09cb3..4c574a39a155 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -13577,9 +13577,10 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, if (!zend_jit_spill_store_inv(jit, op3_addr, real_addr, op1_data_info)) { return 0; } - op3_addr = real_addr; + arg2 = jit_ZVAL_ADDR(jit, real_addr); + } else { + arg2 = jit_ZVAL_ADDR(jit, op3_addr); } - arg2 = jit_ZVAL_ADDR(jit, op3_addr); ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_op_to_typed_ref), reference, arg2, ir_CONST_FC_FUNC(binary_op)); diff --git a/ext/opcache/tests/jit/gh24437.phpt b/ext/opcache/tests/jit/gh24437.phpt new file mode 100644 index 000000000000..35b25e0d4aa8 --- /dev/null +++ b/ext/opcache/tests/jit/gh24437.phpt @@ -0,0 +1,50 @@ +--TEST-- +GH-24437 (JIT: tracing JIT gives wrong sum for `$a[0] += $i + 1` on an array parameter in a loop) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=tracing +--FILE-- + 2])); +$x = 10; +var_dump(g([&$x]), $x); +$c = new C; +var_dump(g([&$c->prop]), $c->prop); +@h([]); +?> +DONE +--EXPECT-- +int(6) +int(16) +int(16) +int(16) +int(16) +DONE