mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Don't treat expression exit as terminator
Same as with throw expressions, this may remove later temporary consuming instructions and thus eliminate live ranges, resulting in a memory leak. We make use of the same hack and don't consider exit a terminator if used in an expression context.
This commit is contained in:
parent
757c1277eb
commit
c9762be566
3 changed files with 14 additions and 6 deletions
|
@ -299,13 +299,13 @@ ZEND_API int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, u
|
||||||
case ZEND_RETURN:
|
case ZEND_RETURN:
|
||||||
case ZEND_RETURN_BY_REF:
|
case ZEND_RETURN_BY_REF:
|
||||||
case ZEND_GENERATOR_RETURN:
|
case ZEND_GENERATOR_RETURN:
|
||||||
case ZEND_EXIT:
|
|
||||||
case ZEND_MATCH_ERROR:
|
case ZEND_MATCH_ERROR:
|
||||||
case ZEND_VERIFY_NEVER_TYPE:
|
case ZEND_VERIFY_NEVER_TYPE:
|
||||||
if (i + 1 < op_array->last) {
|
if (i + 1 < op_array->last) {
|
||||||
BB_START(i + 1);
|
BB_START(i + 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ZEND_EXIT:
|
||||||
case ZEND_THROW:
|
case ZEND_THROW:
|
||||||
/* Don't treat THROW as terminator if it's used in expression context,
|
/* Don't treat THROW as terminator if it's used in expression context,
|
||||||
* as we may lose live ranges when eliminating unreachable code. */
|
* as we may lose live ranges when eliminating unreachable code. */
|
||||||
|
|
|
@ -23,6 +23,9 @@ try {
|
||||||
}
|
}
|
||||||
var_dump(error_reporting());
|
var_dump(error_reporting());
|
||||||
|
|
||||||
|
// Exit also unwinds and thus has the same basic problem.
|
||||||
|
new stdClass(exit);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
Caught
|
Caught
|
||||||
|
|
|
@ -9045,17 +9045,21 @@ static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
|
||||||
static void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
|
static void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
|
||||||
{
|
{
|
||||||
zend_ast *expr_ast = ast->child[0];
|
zend_ast *expr_ast = ast->child[0];
|
||||||
|
znode expr_node;
|
||||||
|
|
||||||
if (expr_ast) {
|
if (expr_ast) {
|
||||||
znode expr_node;
|
|
||||||
zend_compile_expr(&expr_node, expr_ast);
|
zend_compile_expr(&expr_node, expr_ast);
|
||||||
zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
|
|
||||||
} else {
|
} else {
|
||||||
zend_emit_op(NULL, ZEND_EXIT, NULL, NULL);
|
expr_node.op_type = IS_UNUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
result->op_type = IS_CONST;
|
zend_op *opline = zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
|
||||||
ZVAL_TRUE(&result->u.constant);
|
if (result) {
|
||||||
|
/* Mark this as an "expression throw" for opcache. */
|
||||||
|
opline->extended_value = ZEND_THROW_IS_EXPR;
|
||||||
|
result->op_type = IS_CONST;
|
||||||
|
ZVAL_TRUE(&result->u.constant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -9999,6 +10003,7 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
|
||||||
zend_compile_halt_compiler(ast);
|
zend_compile_halt_compiler(ast);
|
||||||
break;
|
break;
|
||||||
case ZEND_AST_THROW:
|
case ZEND_AST_THROW:
|
||||||
|
case ZEND_AST_EXIT:
|
||||||
zend_compile_expr(NULL, ast);
|
zend_compile_expr(NULL, ast);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue