From 69582f2d7187172b96d3064d6e5f108598952444 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 18 Oct 2026 10:18:40 -0400 Subject: [PATCH] Fix GH-24397: Clear vacated MERGE inputs in _zend_jit_fix_merges() _zend_jit_fix_merges() compacts the non-zero inputs of a MERGE or LOOP_BEGIN to the left but left the vacated slots holding their old refs. When a single input survives, the node becomes a BEGIN whose op2 is a label operand, so the stale END ref was read as a label: ir_save() asserted on it, and the aliasing load and store searches stopped at the block as if its address were taken. PHI inputs are compacted the same way but are bounded by inputs_count, and a PHI reduced to COPY already overwrites op2. Fixes GH-24397 --- ext/opcache/jit/zend_jit_ir.c | 5 +++++ ext/opcache/tests/jit/gh24397.phpt | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 ext/opcache/tests/jit/gh24397.phpt diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index e94a86000a0a..a73c6cdf3ca5 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -3754,6 +3754,11 @@ static void _zend_jit_fix_merges(zend_jit_ctx *jit) if (k != n) { ir_ref n2, k2; + /* BEGIN reads op2 as a label, so clear the vacated inputs */ + while (r != q) { + *r = IR_UNUSED; + r++; + } if (k <= 1) { insn->op = IR_BEGIN; insn->inputs_count = 0; diff --git a/ext/opcache/tests/jit/gh24397.phpt b/ext/opcache/tests/jit/gh24397.phpt new file mode 100644 index 000000000000..1ef87a66f3da --- /dev/null +++ b/ext/opcache/tests/jit/gh24397.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-24397 (JIT: stale label operand on a MERGE reduced to BEGIN) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=function +opcache.jit_debug=0x1000000 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECTF-- +%ADone