diff --git a/Zend/Optimizer/zend_cfg.c b/Zend/Optimizer/zend_cfg.c index d3cdbbcd1e3..7aafb10315b 100644 --- a/Zend/Optimizer/zend_cfg.c +++ b/Zend/Optimizer/zend_cfg.c @@ -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_BY_REF: case ZEND_GENERATOR_RETURN: - case ZEND_EXIT: case ZEND_MATCH_ERROR: case ZEND_VERIFY_NEVER_TYPE: if (i + 1 < op_array->last) { BB_START(i + 1); } break; + case ZEND_EXIT: case ZEND_THROW: /* Don't treat THROW as terminator if it's used in expression context, * as we may lose live ranges when eliminating unreachable code. */ diff --git a/Zend/tests/throw/leaks.phpt b/Zend/tests/throw/leaks.phpt index 072f65f2fc8..0f9311a820c 100644 --- a/Zend/tests/throw/leaks.phpt +++ b/Zend/tests/throw/leaks.phpt @@ -23,6 +23,9 @@ try { } var_dump(error_reporting()); +// Exit also unwinds and thus has the same basic problem. +new stdClass(exit); + ?> --EXPECT-- Caught diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 99195793baf..651dda25692 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -9045,17 +9045,21 @@ static void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */ static void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *expr_ast = ast->child[0]; + znode expr_node; if (expr_ast) { - znode expr_node; zend_compile_expr(&expr_node, expr_ast); - zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL); } else { - zend_emit_op(NULL, ZEND_EXIT, NULL, NULL); + expr_node.op_type = IS_UNUSED; } - result->op_type = IS_CONST; - ZVAL_TRUE(&result->u.constant); + zend_op *opline = zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL); + 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); break; case ZEND_AST_THROW: + case ZEND_AST_EXIT: zend_compile_expr(NULL, ast); break; default: