diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index 24a7d200007..d0b52fbfcd1 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -333,7 +333,7 @@ static inline bool can_elide_return_type_check( } static bool opline_supports_assign_contraction( - zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { + zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, int src_var, uint32_t cv_var) { if (opline->opcode == ZEND_NEW) { /* see Zend/tests/generators/aborted_yield_during_new.phpt */ return 0; @@ -367,6 +367,13 @@ static bool opline_supports_assign_contraction( return opline->op1_type != IS_CV || opline->op1.var != cv_var; } + if (opline->opcode == ZEND_ASSIGN_OP + && opline->op1_type == IS_CV + && opline->op1.var == cv_var + && zend_may_throw(opline, &ssa->ops[ssa->vars[src_var].definition], op_array, ssa)) { + return 0; + } + return 1; } @@ -1357,7 +1364,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !ssa->vars[src_var].phi_use_chain && !ssa->vars[src_var].sym_use_chain && opline_supports_assign_contraction( - ssa, &op_array->opcodes[ssa->vars[src_var].definition], + op_array, ssa, &op_array->opcodes[ssa->vars[src_var].definition], src_var, opline->result.var) && !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->result.var), ssa->vars[src_var].definition+1, op_1) @@ -1514,7 +1521,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !ssa->vars[src_var].phi_use_chain && !ssa->vars[src_var].sym_use_chain && opline_supports_assign_contraction( - ssa, &op_array->opcodes[ssa->vars[src_var].definition], + op_array, ssa, &op_array->opcodes[ssa->vars[src_var].definition], src_var, opline->op1.var) && !variable_defined_or_used_in_range(ssa, EX_VAR_TO_NUM(opline->op1.var), ssa->vars[src_var].definition+1, op_1) diff --git a/ext/opcache/tests/opt/assign_op_001.phpt b/ext/opcache/tests/opt/assign_op_001.phpt new file mode 100644 index 00000000000..b9db4202b46 --- /dev/null +++ b/ext/opcache/tests/opt/assign_op_001.phpt @@ -0,0 +1,30 @@ +--TEST-- +ASSIGN_OP 001: Incrrect optimization of ASSIGN_OP may lead to memory leak +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $a in %sassign_op_001.php on line 4 + +Warning: Undefined variable $a in %sassign_op_001.php on line 4 + +Warning: Undefined array key "b" in %sassign_op_001.php on line 7 + +Fatal error: Uncaught TypeError: Unsupported operand types: array + bool in %sassign_op_001.php:4 +Stack trace: +#0 %sassign_op_001.php(10): test() +#1 {main} + thrown in %sassign_op_001.php on line 4 \ No newline at end of file