From 3f00c9367d080bfa6153d6c7673f3ca4fad73c31 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 4 Mar 2019 13:11:12 +0100 Subject: [PATCH] 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. --- NEWS | 4 ++++ ext/opcache/Optimizer/sccp.c | 11 ++++++----- ext/opcache/tests/bug77691.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 ext/opcache/tests/bug77691.phpt 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-- + +--EXPECT-- +string(4) "test" +array(1) { + [0]=> + string(4) "test" +} -- 2.50.0