Skip to content

Commit 0777c51

Browse files
committed
Fix GH-21368 crash: resolve orig_handler at side-trace compile time
zend_jit_escape_if_undef read orig_handler via an op_array pointer captured at parent-trace compile time. That pointer goes stale by the time a side trace compiles for the exit, producing the access violation reported by vibbow on PHP 8.5.5 Windows x64 NTS+FastCGI. Resolve orig_handler against jit->current_op_array. zend_jit_trace_start sets it to trace_buffer->op_array during side-trace compilation; zend_jit_deoptimizer_start leaves it unset, so seed it from exit_info->op_array in zend_jit_trace_exit_to_vm. Create the IR ref via ir_CONST_FC_FUNC so jit->addr_hash registers the handler as IR_FUNC_ADDR. A later ir_CONST_FC_FUNC for the same handler otherwise trips the FUNC_ADDR assertion in jit_CONST_FUNC_PROTO. The x86 ir_CAST_FC_FUNC becomes dead.
1 parent 391ec27 commit 0777c51

2 files changed

Lines changed: 6 additions & 7 deletions

File tree

ext/opcache/jit/zend_jit_ir.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8068,7 +8068,7 @@ static int zend_jit_defined(zend_jit_ctx *jit, const zend_op *opline, uint8_t sm
80688068
return 1;
80698069
}
80708070

8071-
static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, const zend_op_array *op_array, int8_t reg)
8071+
static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, int8_t reg)
80728072
{
80738073
zend_jit_addr reg_addr = ZEND_ADDR_REF_ZVAL(zend_jit_deopt_rload(jit, IR_ADDR, reg));
80748074
ir_ref if_def = ir_IF(jit_Z_TYPE(jit, reg_addr));
@@ -8094,15 +8094,12 @@ static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags,
80948094

80958095
/* We can't use trace_escape() because opcode handler may be overridden by JIT */
80968096
zend_jit_op_array_trace_extension *jit_extension =
8097-
(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
8097+
(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(jit->current_op_array);
80988098
size_t offset = jit_extension->offset;
8099-
ir_ref ref = ir_CONST_ADDR(ZEND_OP_TRACE_INFO((opline - 1), offset)->orig_handler);
8099+
ir_ref ref = ir_CONST_FC_FUNC(ZEND_OP_TRACE_INFO((opline - 1), offset)->orig_handler);
81008100
if (GCC_GLOBAL_REGS) {
81018101
ir_TAILCALL(IR_VOID, ref);
81028102
} else {
8103-
#if defined(IR_TARGET_X86)
8104-
ref = ir_CAST_FC_FUNC(ref);
8105-
#endif
81068103
ir_TAILCALL_1(IR_I32, ref, jit_FP(jit));
81078104
}
81088105

ext/opcache/jit/zend_jit_trace.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3603,7 +3603,7 @@ static int zend_jit_trace_deoptimization(
36033603

36043604
ZEND_ASSERT(STACK_FLAGS(parent_stack, check2) == ZREG_ZVAL_COPY);
36053605
ZEND_ASSERT(reg != ZREG_NONE);
3606-
if (!zend_jit_escape_if_undef(jit, check2, flags, opline, exit_info->op_array, reg)) {
3606+
if (!zend_jit_escape_if_undef(jit, check2, flags, opline, reg)) {
36073607
return 0;
36083608
}
36093609
if (!zend_jit_restore_zval(jit, EX_NUM_TO_VAR(check2), reg)) {
@@ -7374,6 +7374,8 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n
73747374
zend_jit_traces[trace_num].stack_map + zend_jit_traces[trace_num].exit_info[exit_num].stack_offset :
73757375
NULL;
73767376

7377+
ctx.current_op_array = zend_jit_traces[trace_num].exit_info[exit_num].op_array;
7378+
73777379
if (!zend_jit_trace_deoptimization(&ctx,
73787380
&zend_jit_traces[trace_num].exit_info[exit_num],
73797381
stack, stack_size, NULL, NULL,

0 commit comments

Comments
 (0)