diff options
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 28 | ||||
-rw-r--r-- | ext/opcache/Optimizer/pass3.c | 6 | ||||
-rw-r--r-- | ext/opcache/tests/leak_001.phpt | 34 |
3 files changed, 62 insertions, 6 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index a810829628..ee9bda6094 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/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); diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index cb717998d6..3e589df628 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/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; diff --git a/ext/opcache/tests/leak_001.phpt b/ext/opcache/tests/leak_001.phpt new file mode 100644 index 0000000000..c590943fcb --- /dev/null +++ b/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 |