Skip to content

Commit f6f5b5b

Browse files
committed
Fix GH-17144: type inference narrowing on ZEND_FETCH_DIM_W
FETCH_DIM_W stripped MAY_BE_ARRAY_EMPTY when key_type had any valid key bit set. As the key operand's type widened across iterations (e.g. from MAY_BE_ARRAY to MAY_BE_ARRAY|MAY_BE_LONG), key_type transitioned from 0 to non-zero, flipping the strip from inactive to active. The resulting type lost MAY_BE_ARRAY_EMPTY mid-iteration, tripping the narrowing assertion. Stripping unconditionally is unsound: $a = []; $a[$a] = 1; throws before the write, leaving the array empty. Strip only when the key operand is guaranteed a valid array key, i.e. when op2 is IS_UNUSED (append) or t2 contains no MAY_BE_ARRAY or MAY_BE_OBJECT bits. As t2 widens, this condition can only flip from true to false, so the result type monotonically gains MAY_BE_ARRAY_EMPTY back rather than losing it. Test covers both the original narrowing reproducer and the invalid-key throw path. Closes GH-17144
1 parent 9c08243 commit f6f5b5b

2 files changed

Lines changed: 39 additions & 1 deletion

File tree

Zend/Optimizer/zend_inference.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3716,7 +3716,9 @@ static zend_always_inline zend_result _zend_update_type_info(
37163716
break;
37173717
}
37183718
}
3719-
if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG) {
3719+
if (opline->opcode != ZEND_FETCH_DIM_FUNC_ARG
3720+
&& (opline->op2_type == IS_UNUSED
3721+
|| !(t2 & (MAY_BE_ARRAY|MAY_BE_OBJECT)))) {
37203722
tmp &= ~MAY_BE_ARRAY_EMPTY;
37213723
}
37223724
}

Zend/tests/gh17144.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-17144 (Assertion failure during type inference of ZEND_FETCH_DIM_W)
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.jit=1254
7+
--EXTENSIONS--
8+
opcache
9+
--FILE--
10+
<?php
11+
function renderRawGraph(array $parents) {
12+
foreach ($parents as $p) {
13+
foreach ($graph as $graph) {
14+
$graph[$graph]['line'] = 1;
15+
}
16+
$graph[] = [
17+
'line' => 1,
18+
];
19+
}
20+
}
21+
22+
function arrayKeyThrows() {
23+
$a = [];
24+
try {
25+
$a[$a] = 1;
26+
} catch (\Throwable $e) {}
27+
return $a;
28+
}
29+
30+
var_dump(arrayKeyThrows());
31+
echo "Done\n";
32+
?>
33+
--EXPECT--
34+
array(0) {
35+
}
36+
Done

0 commit comments

Comments
 (0)