diff options
author | Dmitry Stogov <dmitry@zend.com> | 2016-08-29 12:02:50 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2016-08-29 12:02:50 +0300 |
commit | b66039db333f730be60c6f6e1925eeb01220e4eb (patch) | |
tree | ac1bb4c17e08f5d269423a7c97e3ece6294ff7cd /ext | |
parent | ca1eb585ee0ef7d2ab5bb4160aa0a36f59d51a48 (diff) | |
download | php-git-b66039db333f730be60c6f6e1925eeb01220e4eb.tar.gz |
Fixed bug #72944 (Null pointer deref in zval_delref_p).
Diffstat (limited to 'ext')
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 5e9b20d191..4b532c4b20 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -561,7 +561,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int convert_to_string((v)); \ } -static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx) +static void strip_nop(zend_code_block *block, zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline = block->start_opline; zend_op *end, *new_end; @@ -575,6 +575,14 @@ static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx) } return; } + if (block->len == 2 + && ((block->start_opline + 1)->opcode == ZEND_JMPZ + || (block->start_opline + 1)->opcode == ZEND_JMPNZ) + && (block->start_opline + 1)->op1_type & (IS_CV|IS_CONST) + && block->start_opline > op_array->opcodes + && zend_is_smart_branch(block->start_opline - 1)) { + break; + } block->start_opline++; block->start_opline_no++; block->len--; @@ -588,10 +596,21 @@ static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx) zend_op *src; int len = 0; + src = opline; while (opline < end && opline->opcode == ZEND_NOP) { + if (opline + 1 < end + && ((opline + 1)->opcode == ZEND_JMPZ + || (opline + 1)->opcode == ZEND_JMPNZ) + && (opline + 1)->op1_type & (IS_CV|IS_CONST) + && opline > op_array->opcodes + && zend_is_smart_branch(opline - 1)) { + /* don't remove NOP, that splits incorrect smart branch */ + opline++; + break; + } + src++; opline++; } - src = opline; while (opline < end && opline->opcode != ZEND_NOP) { opline++; @@ -621,6 +640,14 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, if (block->follow_to) { delete_code_block(block, ctx); } + if (block->len == 2 + && ((block->start_opline + 1)->opcode == ZEND_JMPZ + || (block->start_opline + 1)->opcode == ZEND_JMPNZ) + && (block->start_opline + 1)->op1_type & (IS_CV|IS_CONST) + && block->start_opline > op_array->opcodes + && zend_is_smart_branch(block->start_opline - 1)) { + break; + } return; } block->start_opline++; @@ -1137,7 +1164,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, opline++; } - strip_nop(block, ctx); + strip_nop(block, op_array, ctx); } /* Rebuild plain (optimized) op_array from CFG */ |