summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-30 14:23:46 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-30 14:23:46 +0100
commitbe7eab3202567a1acf0158d281362c20d5051767 (patch)
tree0725e6387de63cc1582e686dde9a37eac765b345
parent01d30f880a0f333650164a20bff52a77af9814d9 (diff)
downloadphp-git-be7eab3202567a1acf0158d281362c20d5051767.tar.gz
Fix live range calculation for FE_FETCH
Op2 is def here, not a use, so treat it accordingly.
-rw-r--r--Zend/tests/fe_fetch_op2_live_range.phpt12
-rw-r--r--Zend/zend_opcode.c12
2 files changed, 23 insertions, 1 deletions
diff --git a/Zend/tests/fe_fetch_op2_live_range.phpt b/Zend/tests/fe_fetch_op2_live_range.phpt
new file mode 100644
index 0000000000..c601e43120
--- /dev/null
+++ b/Zend/tests/fe_fetch_op2_live_range.phpt
@@ -0,0 +1,12 @@
+--TEST--
+FE_FETCH op2 is a def and needs special live range handling
+--FILE--
+<?php
+try {
+ foreach (["test"] as $k => func()[]) {}
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+Call to undefined function func()
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index a128f9436e..d0d49934fe 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -817,7 +817,17 @@ static void zend_calc_live_ranges(
}
if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
uint32_t var_num = EX_VAR_TO_NUM(opline->op2.var) - var_offset;
- if (EXPECTED(last_use[var_num] == (uint32_t) -1)) {
+ if (UNEXPECTED(opline->opcode == ZEND_FE_FETCH_R
+ || opline->opcode == ZEND_FE_FETCH_RW)) {
+ /* OP2 of FE_FETCH is actually a def, not a use. */
+ if (last_use[var_num] != (uint32_t) -1) {
+ if (opnum + 1 != last_use[var_num]) {
+ emit_live_range(
+ op_array, var_num, opnum, last_use[var_num], needs_live_range);
+ }
+ last_use[var_num] = (uint32_t) -1;
+ }
+ } else if (EXPECTED(last_use[var_num] == (uint32_t) -1)) {
#if 1
/* OP_DATA uses only op1 operand */
ZEND_ASSERT(opline->opcode != ZEND_OP_DATA);