mirror of
https://github.com/php/php-src.git
synced 2024-11-27 20:03:40 +08:00
Merge branch 'PHP-7.0' into PHP-7.1
* PHP-7.0: Fixed bug #72944 (Null pointer deref in zval_delref_p).
This commit is contained in:
commit
b5bab0fce8
1
NEWS
1
NEWS
@ -3,6 +3,7 @@ PHP NEWS
|
||||
?? ??? 2016, PHP 7.1.0RC1
|
||||
|
||||
- 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 #72598 (Reference is lost after array_slice()) (Nikita)
|
||||
|
||||
|
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
|
@ -2198,10 +2198,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;
|
||||
}
|
||||
|
@ -791,6 +791,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(const zend_op *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 {
|
||||
|
@ -91,6 +91,15 @@ static void strip_leading_nops(zend_op_array *op_array, zend_basic_block *b)
|
||||
zend_op *opcodes = op_array->opcodes;
|
||||
|
||||
while (b->len > 0 && opcodes[b->start].opcode == ZEND_NOP) {
|
||||
/* check if NOP breaks incorrect smart branch */
|
||||
if (b->len == 2
|
||||
&& (op_array->opcodes[b->start + 1].opcode == ZEND_JMPZ
|
||||
|| op_array->opcodes[b->start + 1].opcode == ZEND_JMPNZ)
|
||||
&& (op_array->opcodes[b->start + 1].op1_type & (IS_CV|IS_CONST))
|
||||
&& b->start > 0
|
||||
&& zend_is_smart_branch(op_array->opcodes + b->start - 1)) {
|
||||
break;
|
||||
}
|
||||
b->start++;
|
||||
b->len--;
|
||||
}
|
||||
@ -114,6 +123,14 @@ static void strip_nops(zend_op_array *op_array, zend_basic_block *b)
|
||||
}
|
||||
j++;
|
||||
}
|
||||
if (i + 1 < b->start + b->len
|
||||
&& (op_array->opcodes[i+1].opcode == ZEND_JMPZ
|
||||
|| op_array->opcodes[i+1].opcode == ZEND_JMPNZ)
|
||||
&& op_array->opcodes[i+1].op1_type & (IS_CV|IS_CONST)
|
||||
&& zend_is_smart_branch(op_array->opcodes + j - 1)) {
|
||||
/* don't remove NOP, that splits incorrect smart branch */
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
b->len = j - b->start;
|
||||
|
@ -149,20 +149,7 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa)
|
||||
i + 1 < op_array->last &&
|
||||
(op_array->opcodes[i+1].opcode == ZEND_JMPZ ||
|
||||
op_array->opcodes[i+1].opcode == ZEND_JMPNZ) &&
|
||||
(op_array->opcodes[i-1].opcode == ZEND_IS_IDENTICAL ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_IS_NOT_IDENTICAL ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_IS_EQUAL ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_IS_NOT_EQUAL ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_IS_SMALLER ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_IS_SMALLER_OR_EQUAL ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_CASE ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_ISSET_ISEMPTY_VAR ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_ISSET_ISEMPTY_STATIC_PROP ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_ISSET_ISEMPTY_PROP_OBJ ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_INSTANCEOF ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_TYPE_CHECK ||
|
||||
op_array->opcodes[i-1].opcode == ZEND_DEFINED))) {
|
||||
zend_is_smart_branch(op_array->opcodes + i - 1))) {
|
||||
if (i != target) {
|
||||
op_array->opcodes[target] = op_array->opcodes[i];
|
||||
ssa->ops[target] = ssa->ops[i];
|
||||
|
@ -109,6 +109,15 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
|
||||
b = blocks + block_map[live_range->start];
|
||||
if (b->flags & ZEND_BB_REACHABLE) {
|
||||
while (b->len > 0 && op_array->opcodes[b->start].opcode == ZEND_NOP) {
|
||||
/* check if NOP breaks incorrect smart branch */
|
||||
if (b->len == 2
|
||||
&& (op_array->opcodes[b->start + 1].opcode == ZEND_JMPZ
|
||||
|| op_array->opcodes[b->start + 1].opcode == ZEND_JMPNZ)
|
||||
&& (op_array->opcodes[b->start + 1].op1_type & (IS_CV|IS_CONST))
|
||||
&& b->start > 0
|
||||
&& zend_is_smart_branch(op_array->opcodes + b->start - 1)) {
|
||||
break;
|
||||
}
|
||||
b->start++;
|
||||
b->len--;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user