summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-03-04 13:11:12 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-03-04 13:11:12 +0100
commit3f00c9367d080bfa6153d6c7673f3ca4fad73c31 (patch)
tree0ec16b7fc32e2b029b722bd33bedfff07455a31a
parent2694953ada29ce4e6869ad4178d7c88581b8752c (diff)
downloadphp-git-3f00c9367d080bfa6153d6c7673f3ca4fad73c31.tar.gz
Fixed bug #77691
We cannot replace an op1_def opcode with an ASSIGN, if it also has a used res_def. Usually this doesn't happen because the res_def use can be eliminated first. The example is a case where operand replacement on the res_def use fails.
-rw-r--r--NEWS4
-rw-r--r--ext/opcache/Optimizer/sccp.c11
-rw-r--r--ext/opcache/tests/bug77691.phpt26
3 files changed, 36 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index f7a1246567..324f95aa95 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,10 @@ PHP NEWS
- MySQLi:
. Fixed bug #77597 (mysqli_fetch_field hangs scripts). (Nikita)
+- Opcache:
+ . Fixed bug #77691 (Opcache passes wrong value for inline array push
+ assignments). (Nikita)
+
- sodium:
. Fixed bug #77646 (sign_detached() strings not terminated). (Frank)
diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c
index 78ce8e7e25..8e0b6bf6ab 100644
--- a/ext/opcache/Optimizer/sccp.c
+++ b/ext/opcache/Optimizer/sccp.c
@@ -1581,7 +1581,10 @@ static int replace_constant_operands(sccp_ctx *ctx) {
zend_ssa_remove_instr(ssa, opline, ssa_op);
removed_ops++;
}
- } else if (ssa_op->op1_def == i) {
+ } else if (ssa_op->op1_def == i &&
+ (ssa_op->result_def < 0 ||
+ (ssa->vars[ssa_op->result_def].use_chain < 0 &&
+ ssa->vars[ssa_op->result_def].phi_use_chain == NULL))) {
/* Compound assign or incdec -> convert to direct ASSIGN */
/* Destroy previous op2 */
@@ -1595,10 +1598,8 @@ static int replace_constant_operands(sccp_ctx *ctx) {
ssa_op->op2_use_chain = -1;
}
- /* Mark result unused, if possible */
- if (ssa_op->result_def >= 0
- && ssa->vars[ssa_op->result_def].use_chain < 0
- && ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
+ /* We checked that result has no uses, mark unused */
+ if (ssa_op->result_def >= 0) {
if (opline->result_type & (IS_TMP_VAR|IS_VAR)) {
zend_optimizer_remove_live_range_ex(op_array, opline->result.var, var->definition);
}
diff --git a/ext/opcache/tests/bug77691.phpt b/ext/opcache/tests/bug77691.phpt
new file mode 100644
index 0000000000..998a3487d1
--- /dev/null
+++ b/ext/opcache/tests/bug77691.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #77691: Opcache passes wrong value for inline array push assignments
+--FILE--
+<?php
+
+if (true) {
+ function dump($str) {
+ var_dump($str);
+ }
+}
+
+function test() {
+ $array = [];
+ dump($array[] = 'test');
+ dump($array);
+}
+
+test();
+
+?>
+--EXPECT--
+string(4) "test"
+array(1) {
+ [0]=>
+ string(4) "test"
+}