Skip to content

Commit 8373828

Browse files
committed
Fix SSA integrity violation for type inference in dead code
The foreach body can never be executed and thus may contain empty types. We should still uphold our SSA integrity invariants in that case.
1 parent 0427dcb commit 8373828

File tree

2 files changed

+37
-15
lines changed

2 files changed

+37
-15
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Make sure type inference upholds invariants for dead arrays
3+
--FILE--
4+
<?php
5+
6+
function test() {
7+
foreach ($a as $v) {
8+
$b[] = $v;
9+
}
10+
}
11+
12+
test();
13+
14+
?>
15+
--EXPECTF--
16+
Notice: Undefined variable: a in %s on line %d
17+
18+
Warning: Invalid argument supplied for foreach() in %s on line %d

ext/opcache/Optimizer/zend_inference.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,24 +2106,28 @@ static uint32_t assign_dim_result_type(
21062106
tmp |= MAY_BE_RC1 | MAY_BE_RCN;
21072107
}
21082108
if (tmp & MAY_BE_ARRAY) {
2109-
if (value_type & MAY_BE_UNDEF) {
2110-
tmp |= MAY_BE_ARRAY_OF_NULL;
2111-
}
2112-
if (dim_op_type == IS_UNUSED) {
2113-
tmp |= MAY_BE_ARRAY_KEY_LONG;
2114-
} else {
2115-
if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
2116-
tmp |= MAY_BE_ARRAY_KEY_LONG;
2109+
/* Only add key type if we have a value type. We want to maintain the invariant that a
2110+
* key type exists iff a value type exists even in dead code that may use empty types. */
2111+
if (value_type & (MAY_BE_ANY|MAY_BE_UNDEF)) {
2112+
if (value_type & MAY_BE_UNDEF) {
2113+
tmp |= MAY_BE_ARRAY_OF_NULL;
21172114
}
2118-
if (dim_type & MAY_BE_STRING) {
2119-
tmp |= MAY_BE_ARRAY_KEY_STRING;
2120-
if (dim_op_type != IS_CONST) {
2121-
// FIXME: numeric string
2115+
if (dim_op_type == IS_UNUSED) {
2116+
tmp |= MAY_BE_ARRAY_KEY_LONG;
2117+
} else {
2118+
if (dim_type & (MAY_BE_LONG|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_RESOURCE|MAY_BE_DOUBLE)) {
21222119
tmp |= MAY_BE_ARRAY_KEY_LONG;
21232120
}
2124-
}
2125-
if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
2126-
tmp |= MAY_BE_ARRAY_KEY_STRING;
2121+
if (dim_type & MAY_BE_STRING) {
2122+
tmp |= MAY_BE_ARRAY_KEY_STRING;
2123+
if (dim_op_type != IS_CONST) {
2124+
// FIXME: numeric string
2125+
tmp |= MAY_BE_ARRAY_KEY_LONG;
2126+
}
2127+
}
2128+
if (dim_type & (MAY_BE_UNDEF|MAY_BE_NULL)) {
2129+
tmp |= MAY_BE_ARRAY_KEY_STRING;
2130+
}
21272131
}
21282132
}
21292133
/* Only add value type if we have a key type. It might be that the key type is illegal

0 commit comments

Comments
 (0)