Skip to content

Commit d79074f

Browse files
committed
Fix phpGH-17577: JIT packed type guard crash
When a guard check is created for a variable to check if it's a packed array, it is possible that there was no prior type check for that variable. This happens in the global scope for example when the variable aliases. In the test, this causes a dereference of address 8 because the integer element in `$a` is interpreted as an array address. This patch adds a type check if a prior one was not inserted. In the aliasing case we also cannot set the stack type nor clear the MAY_BE_GUARD flag.
1 parent 2e02cdf commit d79074f

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

ext/opcache/jit/zend_jit_trace.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -4168,10 +4168,24 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
41684168
&& (ssa->vars[i].use_chain != -1
41694169
|| (ssa->vars[i].phi_use_chain
41704170
&& !(ssa->var_info[ssa->vars[i].phi_use_chain->ssa_var].type & MAY_BE_PACKED_GUARD)))) {
4171+
/* The variable type is not checked in all cases above, for example when alias != NO_ALIAS.
4172+
* We must emit a type check before dereferencing the array in zend_jit_packed_guard(). */
4173+
if ((info & MAY_BE_GUARD) != 0) {
4174+
if (!zend_jit_type_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), IS_ARRAY)) {
4175+
goto jit_failure;
4176+
}
4177+
}
4178+
41714179
if (!zend_jit_packed_guard(&dasm_state, opline, EX_NUM_TO_VAR(i), info)) {
41724180
goto jit_failure;
41734181
}
4174-
info &= ~MAY_BE_PACKED_GUARD;
4182+
4183+
if (ssa->vars[i].alias == NO_ALIAS) {
4184+
/* Aliasing may invalidate these guards at a later point. */
4185+
info &= ~MAY_BE_PACKED_GUARD;
4186+
info &= ~MAY_BE_GUARD;
4187+
}
4188+
41754189
ssa->var_info[i].type = info;
41764190
}
41774191
}

ext/opcache/tests/jit/gh17577.phpt

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-17577 (JIT packed type guard crash)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.jit_buffer_size=16M
7+
opcache.jit_hot_func=1
8+
--FILE--
9+
<?php
10+
$a = array(
11+
array(1,2,3),
12+
0,
13+
);
14+
function my_dump($var) {
15+
}
16+
foreach($a as $b) {
17+
for ($i = 0; $i < 3; $i++) {
18+
my_dump($b[$i]);
19+
}
20+
}
21+
?>
22+
--EXPECTF--
23+
Warning: Trying to access array offset on int in %s on line %d
24+
25+
Warning: Trying to access array offset on int in %s on line %d
26+
27+
Warning: Trying to access array offset on int in %s on line %d

0 commit comments

Comments
 (0)