From 5f13abe6d58f4b155cb0d42d5800faa86af63d71 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 25 Aug 2026 12:12:43 +0200 Subject: [PATCH] Fix zend_jit_trace_find_init_fcall_op() zend_jit_trace_find_init_fcall_op() tries to find the INIT_FCALL opline corresponding to a ZEND_JIT_TRACE_INIT_CALL record, but it fails to do so in the ZEND_JIT_TRACE_FAKE_INIT_CALL case, for nested calls. The first loop is supposed to find the first opline after the sequence of ZEND_JIT_TRACE_INIT_CALL record, but it mistakenly decrements 'p' after initially incrementing it. As a result 'p' eventually points to an invalid record. It works for non-nested calls because the 'p->op == ZEND_JIT_TRACE_VM' condition is true on the first iteration in that case. This can not lead to a crash or miscompilations, but this results in lost optimization opportunities. --- ext/opcache/jit/zend_jit_trace.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 49b8e29c1871..5408b29fc4e8 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -1167,6 +1167,9 @@ static const zend_op *zend_jit_trace_find_init_fcall_op(zend_jit_trace_rec *p, c const zend_op *opline = NULL; int call_level = 0; + /* Scan trace buffer forward to find the first recorded opline after + * the sequence of ZEND_JIT_TRACE_INIT_CALL, and keep track of the + * call level. */ p++; while (1) { if (p->op == ZEND_JIT_TRACE_VM) { @@ -1178,8 +1181,9 @@ static const zend_op *zend_jit_trace_find_init_fcall_op(zend_jit_trace_rec *p, c } else { return NULL; } - p--; + p++; } + /* Scan oplines backward to find the init fcall op */ if (opline) { while (opline > op_array->opcodes) { opline--;