From bdb41ad57d41c4e8d5ca53f53458f0112f68f287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 8 Jan 2025 08:41:07 +0100 Subject: [PATCH 1/2] zend_compile: Do not traverse children of ZEND_AST_CLOSURE in zend_compile_const_expr() --- Zend/zend_compile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 22a751a2e1c88..f426f350e264c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -11293,7 +11293,8 @@ static void zend_compile_const_expr(zend_ast **ast_ptr, void *context) /* {{{ */ break; case ZEND_AST_CLOSURE: zend_compile_const_expr_closure(ast_ptr); - break; + /* Return, because we do not want to traverse the children. */ + return; } zend_ast_apply(ast, zend_compile_const_expr, context); From 6dca0884d56cae39013d532202de03c50ac83615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 11 Dec 2024 12:12:51 +0100 Subject: [PATCH 2/2] Add assertions verifying that zend_ast_decl AST nodes are not treated as regular zend_ast nodes --- Zend/zend_ast.c | 11 ++++++++++- Zend/zend_ast.h | 6 ++++++ ext/opcache/zend_file_cache.c | 6 ++++++ ext/opcache/zend_persist.c | 3 +++ ext/opcache/zend_persist_calc.c | 3 +++ 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 95a67a95b7dde..a278f435fc848 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1088,6 +1088,9 @@ static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast) size += zend_ast_tree_size(list->child[i]); } } + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t i, children = zend_ast_get_num_children(ast); @@ -1141,6 +1144,9 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf) ZVAL_COPY(&new->val, &((zend_ast_zval *) ast)->val); Z_LINENO(new->val) = zend_ast_get_lineno(ast); buf = (void*)((char*)buf + sizeof(zend_ast_zval)); + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t i, children = zend_ast_get_num_children(ast); zend_ast *new = (zend_ast*)buf; @@ -1206,7 +1212,7 @@ ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast) zend_string_release_ex(zend_ast_get_constant_name(ast), 0); } else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) { ZEND_ASSERT(!Z_REFCOUNTED(((zend_ast_zval*)(ast))->val)); - } else if (EXPECTED(ast->kind >= ZEND_AST_FUNC_DECL)) { + } else if (EXPECTED(zend_ast_is_decl(ast))) { zend_ast_decl *decl = (zend_ast_decl *) ast; if (decl->name) { @@ -1237,6 +1243,9 @@ ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *contex for (i = 0; i < list->children; ++i) { fn(&list->child[i], context); } + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t i, children = zend_ast_get_num_children(ast); for (i = 0; i < children; ++i) { diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 6f68a961b7989..363679dda3ff6 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -331,6 +331,10 @@ static zend_always_inline bool zend_ast_is_special(zend_ast *ast) { return (ast->kind >> ZEND_AST_SPECIAL_SHIFT) & 1; } +static zend_always_inline bool zend_ast_is_decl(zend_ast *ast) { + return zend_ast_is_special(ast) && ast->kind >= ZEND_AST_FUNC_DECL; +} + static zend_always_inline bool zend_ast_is_list(zend_ast *ast) { return (ast->kind >> ZEND_AST_IS_LIST_SHIFT) & 1; } @@ -357,6 +361,8 @@ static zend_always_inline zend_string *zend_ast_get_constant_name(zend_ast *ast) static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { ZEND_ASSERT(!zend_ast_is_list(ast)); + ZEND_ASSERT(!zend_ast_is_special(ast)); + return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT; } static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) { diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index f12170e8c9936..41165270598ee 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -366,6 +366,9 @@ static void zend_file_cache_serialize_ast(zend_ast *ast, } else if (ast->kind == ZEND_AST_OP_ARRAY) { /* The op_array itself will be serialized as part of the dynamic_func_defs. */ SERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val)); + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t children = zend_ast_get_num_children(ast); for (i = 0; i < children; i++) { @@ -1248,6 +1251,9 @@ static void zend_file_cache_unserialize_ast(zend_ast *ast, } else if (ast->kind == ZEND_AST_OP_ARRAY) { /* The op_array itself will be unserialized as part of the dynamic_func_defs. */ UNSERIALIZE_PTR(Z_PTR(((zend_ast_zval*)ast)->val)); + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t children = zend_ast_get_num_children(ast); for (i = 0; i < children; i++) { diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 11babd8aa4067..1aedbeb3ddb6b 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -192,6 +192,9 @@ static zend_ast *zend_persist_ast(zend_ast *ast) zend_ast_zval *copy = zend_shared_memdup(ast, sizeof(zend_ast_zval)); zend_persist_op_array(©->val); node = (zend_ast *) copy; + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t children = zend_ast_get_num_children(ast); node = zend_shared_memdup(ast, zend_ast_size(children)); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index fe58d3f2de277..d4082365dbcd7 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -89,6 +89,9 @@ static void zend_persist_ast_calc(zend_ast *ast) } else if (ast->kind == ZEND_AST_OP_ARRAY) { ADD_SIZE(sizeof(zend_ast_zval)); zend_persist_op_array_calc(&((zend_ast_zval*)(ast))->val); + } else if (zend_ast_is_decl(ast)) { + /* Not implemented. */ + ZEND_UNREACHABLE(); } else { uint32_t children = zend_ast_get_num_children(ast); ADD_SIZE(zend_ast_size(children));