Browse Source

Fixed memory leak because of incorrect 'if ();' optimization

pull/1266/merge
Dmitry Stogov 11 years ago
parent
commit
fa1abb5677
  1. 28
      ext/opcache/Optimizer/block_pass.c
  2. 6
      ext/opcache/Optimizer/pass3.c
  3. 34
      ext/opcache/tests/leak_001.phpt

28
ext/opcache/Optimizer/block_pass.c

@ -1403,6 +1403,34 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
break;
}
if (block->op2_to == block->follow_to) {
/* L: JMPZ(X, L+1) -> NOP or FREE(X) */
if (last_op->op1_type == IS_VAR) {
zend_op **Tsource = cfg->Tsource;
zend_op *src = VAR_SOURCE(last_op->op1);
if (src &&
src->opcode != ZEND_FETCH_R &&
src->opcode != ZEND_FETCH_DIM_R &&
src->opcode != ZEND_FETCH_OBJ_R) {
ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED;
MAKE_NOP(last_op);
block->op2_to = NULL;
break;
}
}
if (last_op->op1_type & (IS_VAR|IS_TMP_VAR)) {
last_op->opcode = ZEND_FREE;
last_op->op2.num = 0;
block->op2_to = NULL;
} else {
MAKE_NOP(last_op);
block->op2_to = NULL;
}
break;
}
if (block->op2_to) {
zend_uchar same_type = ZEND_OP1_TYPE(last_op);
uint32_t same_var = VAR_NUM_EX(last_op->op1);

6
ext/opcache/Optimizer/pass3.c

@ -202,12 +202,6 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
/* convert L: JMPZ L+1 to NOP */
if (ZEND_OP2(opline).opline_num == opline_num + 1) {
MAKE_NOP(opline);
goto done_jmp_optimization;
}
while (ZEND_OP2(opline).opline_num < op_array->last) {
int target = ZEND_OP2(opline).opline_num;

34
ext/opcache/tests/leak_001.phpt

@ -0,0 +1,34 @@
--TEST--
Leak 001: Incorrect 'if ();' optimization
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_cache_only=0
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
if (false);
if (true);
if (2 + 3);
$x = 2;
$y = 3;
if ($x + $y);
if ($x);
$a = [[$x]];
if ($a[0]);
if (new stdClass());
$x = 2;
$a = [1,$x];
if ((object)$a);
?>
OK
--EXPECT--
OK
Loading…
Cancel
Save