Skip to content

Commit

Permalink
Fix incorrect optimization of ASSIGN_OP that may lead to memory leak
Browse files Browse the repository at this point in the history
Fixes oss-fuzz #42506
  • Loading branch information
dstogov committed Dec 20, 2021
1 parent 7c674e1 commit e004e84
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 3 deletions.
13 changes: 10 additions & 3 deletions ext/opcache/Optimizer/dfa_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ static inline zend_bool can_elide_return_type_check(
}

static zend_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;
Expand Down Expand Up @@ -357,6 +357,13 @@ static zend_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;
}

Expand Down Expand Up @@ -1310,7 +1317,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)
Expand Down Expand Up @@ -1467,7 +1474,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)
Expand Down
30 changes: 30 additions & 0 deletions ext/opcache/tests/opt/assign_op_001.phpt
Original file line number Diff line number Diff line change
@@ -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--
<?php
function test() {
for ($i = 0; $i < 10; $i++) {
$a = $a += $a < true;
$a += $a;
$a = [];
$a['b'] += 1;
}
}
test();
?>
--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

0 comments on commit e004e84

Please sign in to comment.