diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-03-04 13:11:12 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-03-04 13:11:12 +0100 |
commit | 3f00c9367d080bfa6153d6c7673f3ca4fad73c31 (patch) | |
tree | 0ec16b7fc32e2b029b722bd33bedfff07455a31a | |
parent | 2694953ada29ce4e6869ad4178d7c88581b8752c (diff) | |
download | php-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-- | NEWS | 4 | ||||
-rw-r--r-- | ext/opcache/Optimizer/sccp.c | 11 | ||||
-rw-r--r-- | ext/opcache/tests/bug77691.phpt | 26 |
3 files changed, 36 insertions, 5 deletions
@@ -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" +} |