mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Fixed bug #72944 (Null pointer deref in zval_delref_p).
This commit is contained in:
parent
ca1eb585ee
commit
b66039db33
1
NEWS
1
NEWS
@ -3,6 +3,7 @@ PHP NEWS
|
||||
?? ??? 2016 PHP 7.0.11
|
||||
|
||||
- Core:
|
||||
. Fixed bug #72944 (Null pointer deref in zval_delref_p). (Dmitry)
|
||||
. Fixed bug #72943 (assign_dim on string doesn't reset hval). (Laruence)
|
||||
. Fixed bug #72911 (Memleak in zend_binary_assign_op_obj_helper). (Laruence)
|
||||
. Fixed bug #72813 (Segfault with __get returned by ref). (Laruence)
|
||||
|
12
Zend/tests/bug72944.phpt
Normal file
12
Zend/tests/bug72944.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Bug #72944 (Null pointer deref in zval_delref_p).
|
||||
--FILE--
|
||||
<?php
|
||||
"a"== e & $A = $A? 0 : 0 ?:0;
|
||||
echo "OK\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Use of undefined constant e - assumed 'e' in %sbug72944.php on line 2
|
||||
|
||||
Notice: Undefined variable: A in %sbug72944.php on line 2
|
||||
OK
|
@ -1944,10 +1944,42 @@ static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_is_smart_branch(zend_op *opline) /* {{{ */
|
||||
{
|
||||
switch (opline->opcode) {
|
||||
case ZEND_IS_IDENTICAL:
|
||||
case ZEND_IS_NOT_IDENTICAL:
|
||||
case ZEND_IS_EQUAL:
|
||||
case ZEND_IS_NOT_EQUAL:
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
case ZEND_CASE:
|
||||
case ZEND_ISSET_ISEMPTY_VAR:
|
||||
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
|
||||
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
|
||||
case ZEND_INSTANCEOF:
|
||||
case ZEND_TYPE_CHECK:
|
||||
case ZEND_DEFINED:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint32_t opnum_target) /* {{{ */
|
||||
{
|
||||
uint32_t opnum = get_next_op_number(CG(active_op_array));
|
||||
zend_op *opline = zend_emit_op(NULL, opcode, cond, NULL);
|
||||
zend_op *opline;
|
||||
|
||||
if ((cond->op_type & (IS_CV|IS_CONST))
|
||||
&& opnum > 0
|
||||
&& zend_is_smart_branch(CG(active_op_array)->opcodes + opnum - 1)) {
|
||||
/* emit extra NOP to avoid incorrect SMART_BRANCH in very rare cases */
|
||||
zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
|
||||
opnum = get_next_op_number(CG(active_op_array));
|
||||
}
|
||||
opline = zend_emit_op(NULL, opcode, cond, NULL);
|
||||
opline->op2.opline_num = opnum_target;
|
||||
return opnum;
|
||||
}
|
||||
|
@ -761,6 +761,7 @@ ZEND_API char *zend_make_compiled_string_description(const char *name);
|
||||
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
|
||||
uint32_t zend_get_class_fetch_type(zend_string *name);
|
||||
ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc);
|
||||
ZEND_API int zend_is_smart_branch(zend_op *opline);
|
||||
|
||||
typedef zend_bool (*zend_auto_global_callback)(zend_string *name);
|
||||
typedef struct _zend_auto_global {
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user