From fa3d603ba2edb2c06161ab8e116d7f5fa37d96f6 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 14 Sep 2021 13:14:54 +0200 Subject: [PATCH] Mark ASSIGN result as UNUSED in SCCP We can't drop the ASSIGN entirely, but we should mark the result as UNUSED. Otherwise we'll replace uses of it in operands and will not free the ASSIGN result value. This can happen with non-interned strings, but possibly there's some other cases that can trigger this as well. --- Zend/Optimizer/sccp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 125ba86db74..a19c6306fdf 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -2188,12 +2188,13 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, zend_op *opline = &op_array->opcodes[var->definition]; zend_ssa_op *ssa_op = &ssa->ops[var->definition]; - if (opline->opcode == ZEND_ASSIGN) { - /* Leave assigns to DCE (due to dtor effects) */ - return 0; - } - if (ssa_op->result_def == var_num) { + if (opline->opcode == ZEND_ASSIGN) { + /* We can't drop the ASSIGN, but we can remove the result. */ + opline->result_type = IS_UNUSED; + zend_ssa_remove_result_def(ssa, ssa_op); + return 0; + } if (ssa_op->op1_def >= 0 || ssa_op->op2_def >= 0) { /* we cannot remove instruction that defines other variables */ @@ -2257,6 +2258,11 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, } } } else if (ssa_op->op1_def == var_num) { + if (opline->opcode == ZEND_ASSIGN) { + /* Leave assigns to DCE (due to dtor effects) */ + return 0; + } + /* Compound assign or incdec -> convert to direct ASSIGN */ if (!value) {