diff --git a/NEWS b/NEWS index effe93adba390..b9bfd76525e36 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ PHP NEWS - Core: . Fixed bug GH-8310 (Registry settings are no longer recognized). (cmb) . Fixed potential race condition during resource ID allocation. (ryancaicse) + . Fixed bug GH-8133 (Preloading of constants containing arrays with enums + segfaults). (ilutov) - Date: . Fixed bug GH-7752 (DateTimeZone::getTransitions() returns insufficient diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 0d69bfbaca369..d0a180ee6a9c1 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -750,6 +750,12 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast break; case ZEND_AST_CONST_ENUM_INIT: { + // Preloading will attempt to resolve constants but objects can't be stored in shm + // Aborting here to store the const AST instead + if (CG(in_compilation)) { + return FAILURE; + } + zend_ast *class_name_ast = ast->child[0]; zend_string *class_name = zend_ast_get_str(class_name_ast); @@ -762,13 +768,6 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast : NULL; zend_class_entry *ce = zend_lookup_class(class_name); - if (!ce) { - /* Class may not be available when resolving constants on a dynamically - * declared enum during preloading. */ - ZEND_ASSERT(CG(compiler_options) & ZEND_COMPILE_PRELOAD); - return FAILURE; - } - zend_enum_new(result, ce, case_name, case_value_zv); break; } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index c9ba5cf5551fe..5f6b854d477d0 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3725,19 +3725,6 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e return SUCCESS; } -static zend_result preload_update_constant(zval *val, zend_class_entry *scope) -{ - zval tmp; - ZVAL_COPY(&tmp, val); - if (zval_update_constant_ex(&tmp, scope) == FAILURE || Z_TYPE(tmp) == IS_OBJECT) { - zval_ptr_dtor(&tmp); - return FAILURE; - } - zval_ptr_dtor_nogc(val); - ZVAL_COPY_VALUE(val, &tmp); - return SUCCESS; -} - static bool preload_try_resolve_constants(zend_class_entry *ce) { bool ok, changed, was_changed = 0; @@ -3751,7 +3738,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { val = &c->value; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - if (EXPECTED(preload_update_constant(val, c->ce) == SUCCESS)) { + if (EXPECTED(zval_update_constant_ex(val, c->ce) == SUCCESS)) { was_changed = changed = 1; } else { ok = 0; @@ -3769,7 +3756,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) val = &ce->default_properties_table[i]; if (Z_TYPE_P(val) == IS_CONSTANT_AST) { zend_property_info *prop = ce->properties_info_table[i]; - if (UNEXPECTED(preload_update_constant(val, prop->ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, prop->ce) != SUCCESS)) { resolved = ok = 0; } } @@ -3785,7 +3772,7 @@ static bool preload_try_resolve_constants(zend_class_entry *ce) val = ce->default_static_members_table + ce->default_static_members_count - 1; while (count) { if (Z_TYPE_P(val) == IS_CONSTANT_AST) { - if (UNEXPECTED(preload_update_constant(val, ce) != SUCCESS)) { + if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) { resolved = ok = 0; } } diff --git a/ext/opcache/tests/gh8133.inc b/ext/opcache/tests/gh8133.inc new file mode 100644 index 0000000000000..11c38e62e140b --- /dev/null +++ b/ext/opcache/tests/gh8133.inc @@ -0,0 +1,12 @@ + +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + enum(Foo::Bar) + [1]=> + enum(Foo::Baz) +} +array(2) { + [0]=> + enum(Foo::Bar) + [1]=> + enum(Foo::Baz) +}