Skip to content

Commit 7987358

Browse files
committed
Fix GH-24471: Tracing JIT reads stale float temporary on side exit
Don't bind a CV to its VM slot when its IR ref was emitted by an earlier opline (e.g. MUL by 1.0 folded to op1, or a CSE'd expression). The ref may be shared with another live var, whose snapshot entry would then be wrongly marked type_only. Fixes GH-24471
1 parent aa098d7 commit 7987358

5 files changed

Lines changed: 52 additions & 0 deletions

File tree

‎ext/opcache/jit/zend_jit.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
14951495
for (i = ssa->cfg.blocks[b].start; i <= end; i++) {
14961496
zend_ssa_op *ssa_op = ssa->ops ? &ssa->ops[i] : NULL;
14971497
opline = op_array->opcodes + i;
1498+
ctx.op_start_ref = ctx.ctx.insns_count;
14981499
if (zend_jit_inc_call_level(opline->opcode)) {
14991500
call_level++;
15001501
}

‎ext/opcache/jit/zend_jit_ir.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ typedef struct _zend_jit_ctx {
294294
ir_ref *bb_edges;
295295
zend_jit_trace_info *trace;
296296
zend_jit_reg_var *ra;
297+
ir_ref op_start_ref;
297298
int delay_var;
298299
ir_refs *delay_refs;
299300
ir_ref eg_exception_addr;
@@ -1352,6 +1353,8 @@ static bool zend_jit_spilling_may_cause_conflict(zend_jit_ctx *jit, int var, ir_
13521353
&& jit->ra[jit->ssa->ops[jit->ssa->vars[var].definition].op2_use].ref == val) {
13531354
/* Avoid spill conflict between of ASSIGN.op1_def and ASSIGN.op1_use */
13541355
return 1;
1356+
} else if (val < jit->op_start_ref) {
1357+
return 1;
13551358
}
13561359
return 0;
13571360
}
@@ -2809,6 +2812,7 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
28092812
jit->bb_edges = NULL;
28102813
jit->trace = NULL;
28112814
jit->ra = NULL;
2815+
jit->op_start_ref = IR_UNUSED;
28122816
jit->delay_var = -1;
28132817
jit->delay_refs = NULL;
28142818
jit->eg_exception_addr = 0;

‎ext/opcache/jit/zend_jit_trace.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4385,6 +4385,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
43854385
bool gen_handler = false;
43864386

43874387
opline = p->opline;
4388+
jit->op_start_ref = jit->ctx.insns_count;
43884389
if (op1_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
43894390
op1_type = IS_UNKNOWN;
43904391
}

‎ext/opcache/tests/jit/gh24471.phpt‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-24471 (Tracing JIT: float temporary marked type_only in side trace exit, VM reads stale value)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit=tracing
9+
--FILE--
10+
<?php
11+
function f($x, $y) {
12+
$d = ($x + 0.5) * ($y === [1] ? 2.0 : 1.0);
13+
return $d;
14+
}
15+
$ys = array_fill(0, 100, [0]);
16+
$ys[] = [1];
17+
foreach ($ys as $i => $y) {
18+
$r = f($i, $y);
19+
}
20+
var_dump($r);
21+
?>
22+
--EXPECT--
23+
float(201)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-24471 (Tracing JIT: CSE'd float temporary marked type_only in side exit)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.jit=tracing
9+
--FILE--
10+
<?php
11+
function f($x, $y) {
12+
$r = ($x + 0.5) + ($d = $x + 0.5) * ($y === [1] ? 2.0 : 3.0);
13+
return $r + $d;
14+
}
15+
$ys = array_fill(0, 100, [0]);
16+
$ys[] = [1];
17+
foreach ($ys as $i => $y) {
18+
$r = f($i, $y);
19+
}
20+
var_dump($r);
21+
?>
22+
--EXPECT--
23+
float(402)

0 commit comments

Comments
 (0)