summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-08-29 12:02:50 +0300
committerDmitry Stogov <dmitry@zend.com>2016-08-29 12:02:50 +0300
commitb66039db333f730be60c6f6e1925eeb01220e4eb (patch)
treeac1bb4c17e08f5d269423a7c97e3ece6294ff7cd /ext
parentca1eb585ee0ef7d2ab5bb4160aa0a36f59d51a48 (diff)
downloadphp-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.c33
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 */