diff --git a/Zend/tests/enum/empty-from.phpt b/Zend/tests/enum/empty-from.phpt new file mode 100644 index 0000000000000..db42c78ed31c7 --- /dev/null +++ b/Zend/tests/enum/empty-from.phpt @@ -0,0 +1,12 @@ +--TEST-- +Empty enum with from/tryFrom doens't segfault +--FILE-- + +--EXPECT-- +NULL diff --git a/Zend/tests/enum/magic-constants.phpt b/Zend/tests/enum/magic-constants.phpt new file mode 100644 index 0000000000000..7a11d7785d7a4 --- /dev/null +++ b/Zend/tests/enum/magic-constants.phpt @@ -0,0 +1,14 @@ +--TEST-- +Backed enums can contain magic constants +--FILE-- +value, "\n"; + +?> +--EXPECTF-- +%smagic-constants.php diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 728feded60896..06a21944443dc 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -10473,6 +10473,9 @@ static void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ case ZEND_AST_NAMED_ARG: zend_eval_const_expr(&ast->child[1]); return; + case ZEND_AST_CONST_ENUM_INIT: + zend_eval_const_expr(&ast->child[2]); + return; default: return; } diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index a4a450d22fba6..7e8654942f216 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -187,6 +187,7 @@ void zend_enum_add_interfaces(zend_class_entry *ce) zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) { ZEND_ASSERT(ce->ce_flags & ZEND_ACC_ENUM); + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); ZEND_ASSERT(ce->type == ZEND_USER_CLASS); uint32_t backing_type = ce->enum_backing_type; @@ -199,7 +200,7 @@ zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) zend_string *name; zval *val; - ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(&ce->constants_table, name, val) { + ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(CE_CONSTANTS_TABLE(ce), name, val) { zend_class_constant *c = Z_PTR_P(val); if ((ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) == 0) { continue; @@ -281,6 +282,9 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas return FAILURE; } } + if (!ce->backed_enum_table) { + goto not_found; + } zval *case_name_zv; if (ce->enum_backing_type == IS_LONG) { @@ -292,6 +296,7 @@ ZEND_API zend_result zend_enum_get_case_by_value(zend_object **result, zend_clas } if (case_name_zv == NULL) { +not_found: if (try) { *result = NULL; return SUCCESS; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e203556a8ecd7..9822ef692a83d 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -346,6 +346,12 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) } } + if (ce->type == ZEND_USER_CLASS && ce->backed_enum_table) { + ZEND_ASSERT(!(ce->ce_flags & ZEND_ACC_IMMUTABLE)); + zend_hash_release(ce->backed_enum_table); + ce->backed_enum_table = NULL; + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { zend_op_array *op_array; ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {