mirror of
https://github.com/php/php-src.git
synced 2024-12-14 04:16:30 +08:00
Merge branch 'PHP-8.2'
* PHP-8.2: Fix GH-11245 (In some specific cases SWITCH with one default statement will cause segfault)
This commit is contained in:
commit
24ff7eee3f
@ -264,6 +264,10 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
break;
|
||||
|
||||
case ZEND_FREE:
|
||||
/* Note: Only remove the source if the source is local to this block.
|
||||
* If it's not local, then the other blocks successors must also eventually either FREE or consume the temporary,
|
||||
* hence removing the temporary is not safe in the general case, especially when other consumers are not FREE.
|
||||
* A FREE may not be removed without also removing the source's result, because otherwise that would cause a memory leak. */
|
||||
if (opline->op1_type == IS_TMP_VAR) {
|
||||
src = VAR_SOURCE(opline->op1);
|
||||
if (src) {
|
||||
@ -272,6 +276,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
case ZEND_BOOL_NOT:
|
||||
/* T = BOOL(X), FREE(T) => T = BOOL(X) */
|
||||
/* The remaining BOOL is removed by a separate optimization */
|
||||
/* The source is a bool, no source removals take place, so this may be done non-locally. */
|
||||
VAR_SOURCE(opline->op1) = NULL;
|
||||
MAKE_NOP(opline);
|
||||
++(*opt_count);
|
||||
@ -290,6 +295,9 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
case ZEND_PRE_DEC_OBJ:
|
||||
case ZEND_PRE_INC_STATIC_PROP:
|
||||
case ZEND_PRE_DEC_STATIC_PROP:
|
||||
if (src < op_array->opcodes + block->start) {
|
||||
break;
|
||||
}
|
||||
src->result_type = IS_UNUSED;
|
||||
VAR_SOURCE(opline->op1) = NULL;
|
||||
MAKE_NOP(opline);
|
||||
@ -302,7 +310,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
} else if (opline->op1_type == IS_VAR) {
|
||||
src = VAR_SOURCE(opline->op1);
|
||||
/* V = OP, FREE(V) => OP. NOP */
|
||||
if (src &&
|
||||
if (src >= op_array->opcodes + block->start &&
|
||||
src->opcode != ZEND_FETCH_R &&
|
||||
src->opcode != ZEND_FETCH_STATIC_PROP_R &&
|
||||
src->opcode != ZEND_FETCH_DIM_R &&
|
||||
|
33
ext/opcache/tests/opt/gh11245_1.phpt
Normal file
33
ext/opcache/tests/opt/gh11245_1.phpt
Normal file
@ -0,0 +1,33 @@
|
||||
--TEST--
|
||||
GH-11245: In some specific cases SWITCH with one default statement will cause segfault (VAR variation)
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.optimization_level=0x7FFFBFFF
|
||||
opcache.opt_debug_level=0x20000
|
||||
opcache.preload=
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--FILE--
|
||||
<?php
|
||||
function xx() { return "somegarbage"; }
|
||||
switch (xx()) {
|
||||
default:
|
||||
if (!empty($xx)) {return;}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=4, args=0, vars=1, tmps=1)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 T1 = ISSET_ISEMPTY_CV (empty) CV0($xx)
|
||||
0001 JMPNZ T1 0003
|
||||
0002 RETURN null
|
||||
0003 RETURN int(1)
|
||||
|
||||
xx:
|
||||
; (lines=1, args=0, vars=0, tmps=0)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 RETURN string("somegarbage")
|
35
ext/opcache/tests/opt/gh11245_2.phpt
Normal file
35
ext/opcache/tests/opt/gh11245_2.phpt
Normal file
@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
GH-11245: In some specific cases SWITCH with one default statement will cause segfault (TMP variation)
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.optimization_level=0x7FFFBFFF
|
||||
opcache.opt_debug_level=0x20000
|
||||
opcache.preload=
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--FILE--
|
||||
<?php
|
||||
class X {
|
||||
// Chosen to test for a memory leak.
|
||||
static $prop = "aa";
|
||||
}
|
||||
switch (++X::$prop) {
|
||||
default:
|
||||
if (empty($xx)) {return;}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
$_main:
|
||||
; (lines=7, args=0, vars=1, tmps=2)
|
||||
; (after optimizer)
|
||||
; %s
|
||||
0000 T1 = PRE_INC_STATIC_PROP string("prop") string("X")
|
||||
0001 T2 = ISSET_ISEMPTY_CV (empty) CV0($xx)
|
||||
0002 JMPZ T2 0005
|
||||
0003 FREE T1
|
||||
0004 RETURN null
|
||||
0005 FREE T1
|
||||
0006 RETURN int(1)
|
||||
LIVE RANGES:
|
||||
1: 0001 - 0005 (tmp/var)
|
Loading…
Reference in New Issue
Block a user