Skip to content

Commit 0549f75

Browse files
committed
Convert exit/die constants to function call at compile time
1 parent d4fa6df commit 0549f75

File tree

3 files changed

+31
-10
lines changed

3 files changed

+31
-10
lines changed

Zend/zend_compile.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7714,7 +7714,7 @@ static zend_string *zend_begin_func_decl(znode *result, zend_op_array *op_array,
77147714
zend_string *separator = zend_empty_string;
77157715
zend_string *function = filename;
77167716
char *parens = "";
7717-
7717+
77187718
if (CG(active_op_array) && CG(active_op_array)->function_name) {
77197719
if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
77207720
/* If the parent function is a closure, don't redundantly
@@ -8714,6 +8714,13 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
87148714
value_node.op_type = IS_CONST;
87158715
zend_const_expr_to_zval(value_zv, value_ast_ptr, /* allow_dynamic */ true);
87168716

8717+
if (UNEXPECTED(
8718+
zend_string_equals_literal_ci(unqualified_name, "exit")
8719+
|| zend_string_equals_literal_ci(unqualified_name, "die")
8720+
)) {
8721+
zend_throw_error(NULL, "Cannot define constant with name %s", ZSTR_VAL(unqualified_name));
8722+
return;
8723+
}
87178724
if (zend_get_special_const(ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name))) {
87188725
zend_error_noreturn(E_COMPILE_ERROR,
87198726
"Cannot redeclare constant '%s'", ZSTR_VAL(unqualified_name));
@@ -10009,16 +10016,36 @@ static void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
1000910016

1001010017
bool is_fully_qualified;
1001110018
zend_string *orig_name = zend_ast_get_str(name_ast);
10012-
zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
1001310019

10020+
/* The fake "constants" exit and die must be converted to a function call for exit() */
1001410021
if (UNEXPECTED(
1001510022
zend_string_equals_literal_ci(orig_name, "exit")
1001610023
|| zend_string_equals_literal_ci(orig_name, "die")
1001710024
)) {
10018-
zend_throw_error(NULL, "Cannot define constant with name %s", ZSTR_VAL(orig_name));
10025+
zval *fbc_zv = zend_hash_find(CG(function_table), ZSTR_KNOWN(ZEND_STR_EXIT));
10026+
ZEND_ASSERT(fbc_zv && "exit() function should always exist");
10027+
zend_function *fbc = Z_PTR_P(fbc_zv);
10028+
10029+
znode name_node;
10030+
name_node.op_type = IS_CONST;
10031+
ZVAL_STR(&name_node.u.constant, ZSTR_KNOWN(ZEND_STR_EXIT));
10032+
10033+
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
10034+
opline->result.num = zend_alloc_cache_slot();
10035+
10036+
/* Store offset to function from symbol table in op2.extra. */
10037+
{
10038+
Bucket *fbc_bucket = (Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val));
10039+
Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData;
10040+
}
10041+
10042+
zend_ast *args_list = zend_ast_create_list_0(ZEND_AST_ARG_LIST);
10043+
zend_compile_call_common(result, args_list, fbc, ast->lineno);
1001910044
return;
1002010045
}
1002110046

10047+
zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
10048+
1002210049
if (zend_string_equals_literal(resolved_name, "__COMPILER_HALT_OFFSET__") || (name_ast->attr != ZEND_NAME_RELATIVE && zend_string_equals_literal(orig_name, "__COMPILER_HALT_OFFSET__"))) {
1002310050
zend_ast *last = CG(ast);
1002410051

Zend/zend_execute.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5017,13 +5017,6 @@ static zend_always_inline zend_result _zend_quick_get_constant(
50175017
}
50185018

50195019
if (!c) {
5020-
if (UNEXPECTED(
5021-
zend_string_equals_literal_ci(Z_STR_P(key), "exit")
5022-
|| zend_string_equals_literal_ci(Z_STR_P(key), "die")
5023-
)) {
5024-
zend_throw_unwind_exit();
5025-
return FAILURE;
5026-
}
50275020
if (!check_defined_only) {
50285021
zend_throw_error(NULL, "Undefined constant \"%s\"", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)));
50295022
ZVAL_UNDEF(EX_VAR(opline->result.var));

Zend/zend_string.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
572572
_(ZEND_STR_ARGS, "args") \
573573
_(ZEND_STR_UNKNOWN, "unknown") \
574574
_(ZEND_STR_UNKNOWN_CAPITALIZED, "Unknown") \
575+
_(ZEND_STR_EXIT, "exit") \
575576
_(ZEND_STR_EVAL, "eval") \
576577
_(ZEND_STR_INCLUDE, "include") \
577578
_(ZEND_STR_REQUIRE, "require") \

0 commit comments

Comments
 (0)