diff --git a/Zend/tests/gc/gc_045.phpt b/Zend/tests/gc/gc_045.phpt index 1762be5db1ad9..cbb1fc71e79f9 100644 --- a/Zend/tests/gc/gc_045.phpt +++ b/Zend/tests/gc/gc_045.phpt @@ -11,6 +11,9 @@ class GlobalData class Value { + /* Force object to be added to GC, even though it is acyclic. */ + public $dummy; + public function __destruct() { new Bar(); @@ -19,6 +22,9 @@ class Value class Bar { + /* Force object to be added to GC, even though it is acyclic. */ + public $dummy; + public function __construct() { GlobalData::$bar = $this; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index fd5b7c8db7966..6f7f0f1b323c0 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4494,6 +4494,27 @@ static zend_always_inline bool is_persistent_class(zend_class_entry *ce) { && ce->info.internal.module->type == MODULE_PERSISTENT; } +static bool zend_type_may_be_cyclic(zend_type type) +{ + if (!ZEND_TYPE_IS_SET(type)) { + return true; + } + + if (!ZEND_TYPE_IS_COMPLEX(type)) { + return ZEND_TYPE_PURE_MASK(type) & (MAY_BE_OBJECT|MAY_BE_ARRAY); + } else if (ZEND_TYPE_IS_UNION(type)) { + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) { + if (zend_type_may_be_cyclic(*list_type)) { + return true; + } + } ZEND_TYPE_LIST_FOREACH_END(); + return false; + } + + return true; +} + ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type) /* {{{ */ { zend_property_info *property_info, *property_info_ptr; @@ -4506,6 +4527,12 @@ ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, z } } + if (!(access_type & ZEND_ACC_STATIC) + && !(ce->ce_flags & ZEND_ACC_MAY_BE_CYCLIC) + && zend_type_may_be_cyclic(type)) { + ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; + } + if (ce->type == ZEND_INTERNAL_CLASS) { property_info = pemalloc(sizeof(zend_property_info), 1); } else { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 629aa7d51a840..54899f25945a6 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -705,6 +705,9 @@ void zend_register_closure_ce(void) /* {{{ */ zend_ce_closure = register_class_Closure(); zend_ce_closure->create_object = zend_closure_new; zend_ce_closure->default_object_handlers = &closure_handlers; + /* FIXME: Potentially improve during construction of closure? static closures + * not binding by references can't be cyclic. */ + zend_ce_closure->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&closure_handlers, &std_object_handlers, sizeof(zend_object_handlers)); closure_handlers.free_obj = zend_closure_free_storage; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 1eaf3ef686e79..5f3634ae4b894 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -267,7 +267,7 @@ typedef struct _zend_oparray_context { #define ZEND_ACC_PROTECTED_SET (1 << 11) /* | | X | */ #define ZEND_ACC_PRIVATE_SET (1 << 12) /* | | X | */ /* | | | */ -/* Class Flags (unused: 30,31) | | | */ +/* Class Flags (unused: 31) | | | */ /* =========== | | | */ /* | | | */ /* Special class types | | | */ @@ -333,6 +333,9 @@ typedef struct _zend_oparray_context { /* Class cannot be serialized or unserialized | | | */ #define ZEND_ACC_NOT_SERIALIZABLE (1 << 29) /* X | | | */ /* | | | */ +/* Object may be the root of a cycle | | | */ +#define ZEND_ACC_MAY_BE_CYCLIC (1 << 30) /* X | | | */ +/* | | | */ /* Function Flags (unused: 29-30) | | | */ /* ============== | | | */ /* | | | */ diff --git a/Zend/zend_fibers.c b/Zend/zend_fibers.c index 97b7cdcc911b7..da0a2a5f16eb1 100644 --- a/Zend/zend_fibers.c +++ b/Zend/zend_fibers.c @@ -1107,6 +1107,7 @@ void zend_register_fiber_ce(void) zend_ce_fiber = register_class_Fiber(); zend_ce_fiber->create_object = zend_fiber_object_create; zend_ce_fiber->default_object_handlers = &zend_fiber_handlers; + zend_ce_fiber->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; zend_fiber_handlers = std_object_handlers; zend_fiber_handlers.dtor_obj = zend_fiber_object_destroy; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a6ea91a7425b9..d847da5e93942 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -1215,6 +1215,7 @@ void zend_register_generator_ce(void) /* {{{ */ /* get_iterator has to be assigned *after* implementing the interface */ zend_ce_generator->get_iterator = zend_generator_get_iterator; zend_ce_generator->default_object_handlers = &zend_generator_handlers; + zend_ce_generator->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&zend_generator_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_generator_handlers.free_obj = zend_generator_free_storage; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 3557b14bb9740..76aed3fea04c2 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1810,6 +1810,7 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par ce->parent = parent_ce; ce->default_object_handlers = parent_ce->default_object_handlers; ce->ce_flags |= ZEND_ACC_RESOLVED_PARENT; + ce->ce_flags |= (parent_ce->ce_flags & ZEND_ACC_MAY_BE_CYCLIC); /* Inherit properties */ if (parent_ce->default_properties_count) { @@ -2832,6 +2833,9 @@ static void zend_do_traits_property_binding(zend_class_entry *ce, zend_class_ent if (!traits[i]) { continue; } + + ce->ce_flags |= (traits[i]->ce_flags & ZEND_ACC_MAY_BE_CYCLIC); + ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&traits[i]->properties_info, prop_name, property_info) { uint32_t flags = property_info->flags; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 0709d05580dc8..8aa5c243110d5 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -70,6 +70,8 @@ ZEND_API HashTable *rebuild_object_properties_internal(zend_object *zobj) /* {{{ zend_class_entry *ce = zobj->ce; int i; + GC_TYPE_INFO(zobj) &= ~(GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT); + zobj->properties = zend_new_array(ce->default_properties_count); if (ce->default_properties_count) { zend_hash_real_init_mixed(zobj->properties); diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index fd0e97c5f4131..5dbd411c623f8 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -31,6 +31,9 @@ static zend_always_inline void _zend_object_std_init(zend_object *object, zend_c { GC_SET_REFCOUNT(object, 1); GC_TYPE_INFO(object) = GC_OBJECT; + if (!(ce->ce_flags & ZEND_ACC_MAY_BE_CYCLIC)) { + GC_TYPE_INFO(object) |= (GC_NOT_COLLECTABLE << GC_FLAGS_SHIFT); + } object->ce = ce; object->extra_flags = 0; object->handlers = ce->default_object_handlers; diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index cf363cd12595c..2dce20257e689 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -788,6 +788,7 @@ void zend_register_weakref_ce(void) /* {{{ */ zend_ce_weakmap->create_object = zend_weakmap_create_object; zend_ce_weakmap->get_iterator = zend_weakmap_get_iterator; zend_ce_weakmap->default_object_handlers = &zend_weakmap_handlers; + zend_ce_weakmap->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&zend_weakmap_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_weakmap_handlers.offset = XtOffsetOf(zend_weakmap, std); diff --git a/ext/curl/interface.c b/ext/curl/interface.c index aba5273d5496c..328ea4e0a674a 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -395,6 +395,7 @@ PHP_MINIT_FUNCTION(curl) curl_ce = register_class_CurlHandle(); curl_ce->create_object = curl_create_object; curl_ce->default_object_handlers = &curl_object_handlers; + curl_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&curl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); curl_object_handlers.offset = XtOffsetOf(php_curl, std); diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 6456cf6f813e4..244c3b078a752 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -606,6 +606,7 @@ static zend_object_handlers curl_multi_handlers; void curl_multi_register_handlers(void) { curl_multi_ce->create_object = curl_multi_create_object; curl_multi_ce->default_object_handlers = &curl_multi_handlers; + curl_multi_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&curl_multi_handlers, &std_object_handlers, sizeof(zend_object_handlers)); curl_multi_handlers.offset = XtOffsetOf(php_curlm, std); diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 21741166c61aa..b92f2d843d4b6 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -1292,6 +1292,7 @@ PHP_MINIT_FUNCTION(dom) dom_xpath_class_entry = register_class_DOMXPath(); dom_xpath_class_entry->create_object = dom_xpath_objects_new; dom_xpath_class_entry->default_object_handlers = &dom_xpath_object_handlers; + dom_xpath_class_entry->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; zend_hash_init(&dom_xpath_prop_handlers, 0, NULL, NULL, true); DOM_REGISTER_PROP_HANDLER(&dom_xpath_prop_handlers, "document", dom_xpath_document_read, NULL); @@ -1301,6 +1302,7 @@ PHP_MINIT_FUNCTION(dom) dom_modern_xpath_class_entry = register_class_Dom_XPath(); dom_modern_xpath_class_entry->create_object = dom_xpath_objects_new; dom_modern_xpath_class_entry->default_object_handlers = &dom_xpath_object_handlers; + dom_modern_xpath_class_entry->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; zend_hash_add_new_ptr(&classes, dom_modern_xpath_class_entry->name, &dom_xpath_prop_handlers); #endif diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 782639be0758e..611c8a490b96f 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1449,6 +1449,7 @@ void pdo_dbh_init(int module_number) pdo_dbh_ce = register_class_PDO(); pdo_dbh_ce->create_object = pdo_dbh_new; pdo_dbh_ce->default_object_handlers = &pdo_dbh_object_handlers; + pdo_dbh_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index a39b7a3b06804..df131685a16a1 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2491,6 +2491,7 @@ void pdo_stmt_init(void) pdo_dbstmt_ce->get_iterator = pdo_stmt_iter_get; pdo_dbstmt_ce->create_object = pdo_dbstmt_new; pdo_dbstmt_ce->default_object_handlers = &pdo_dbstmt_object_handlers; + pdo_dbstmt_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&pdo_dbstmt_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); pdo_dbstmt_object_handlers.offset = XtOffsetOf(pdo_stmt_t, std); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index f5e463699b1b5..9b60374f8de89 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -4343,6 +4343,16 @@ ZEND_METHOD(ReflectionClass, getAttributes) } /* }}} */ +ZEND_METHOD(ReflectionClass, mayBeCyclic) +{ + reflection_object *intern; + zend_class_entry *ce; + + GET_REFLECTION_OBJECT_PTR(ce); + + RETURN_BOOL(ce->ce_flags & ZEND_ACC_MAY_BE_CYCLIC); +} + /* {{{ Returns the class' constructor if there is one, NULL otherwise */ ZEND_METHOD(ReflectionClass, getConstructor) { @@ -7682,91 +7692,113 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */ reflection_function_abstract_ptr = register_class_ReflectionFunctionAbstract(reflector_ptr); reflection_function_abstract_ptr->default_object_handlers = &reflection_object_handlers; + reflection_function_abstract_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_function_abstract_ptr->create_object = reflection_objects_new; reflection_function_ptr = register_class_ReflectionFunction(reflection_function_abstract_ptr); reflection_function_ptr->create_object = reflection_objects_new; reflection_function_ptr->default_object_handlers = &reflection_object_handlers; + reflection_function_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_generator_ptr = register_class_ReflectionGenerator(); reflection_generator_ptr->create_object = reflection_objects_new; reflection_generator_ptr->default_object_handlers = &reflection_object_handlers; + reflection_generator_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_parameter_ptr = register_class_ReflectionParameter(reflector_ptr); reflection_parameter_ptr->create_object = reflection_objects_new; reflection_parameter_ptr->default_object_handlers = &reflection_object_handlers; + reflection_parameter_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_type_ptr = register_class_ReflectionType(zend_ce_stringable); reflection_type_ptr->create_object = reflection_objects_new; reflection_type_ptr->default_object_handlers = &reflection_object_handlers; + reflection_type_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_named_type_ptr = register_class_ReflectionNamedType(reflection_type_ptr); reflection_named_type_ptr->create_object = reflection_objects_new; reflection_named_type_ptr->default_object_handlers = &reflection_object_handlers; + reflection_named_type_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_union_type_ptr = register_class_ReflectionUnionType(reflection_type_ptr); reflection_union_type_ptr->create_object = reflection_objects_new; reflection_union_type_ptr->default_object_handlers = &reflection_object_handlers; + reflection_union_type_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_intersection_type_ptr = register_class_ReflectionIntersectionType(reflection_type_ptr); reflection_intersection_type_ptr->create_object = reflection_objects_new; reflection_intersection_type_ptr->default_object_handlers = &reflection_object_handlers; + reflection_intersection_type_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_method_ptr = register_class_ReflectionMethod(reflection_function_abstract_ptr); reflection_method_ptr->create_object = reflection_objects_new; reflection_method_ptr->default_object_handlers = &reflection_object_handlers; + reflection_method_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_class_ptr = register_class_ReflectionClass(reflector_ptr); reflection_class_ptr->create_object = reflection_objects_new; reflection_class_ptr->default_object_handlers = &reflection_object_handlers; + reflection_class_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_object_ptr = register_class_ReflectionObject(reflection_class_ptr); reflection_object_ptr->create_object = reflection_objects_new; reflection_object_ptr->default_object_handlers = &reflection_object_handlers; + reflection_object_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_property_ptr = register_class_ReflectionProperty(reflector_ptr); reflection_property_ptr->create_object = reflection_objects_new; reflection_property_ptr->default_object_handlers = &reflection_object_handlers; + reflection_property_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_class_constant_ptr = register_class_ReflectionClassConstant(reflector_ptr); reflection_class_constant_ptr->create_object = reflection_objects_new; reflection_class_constant_ptr->default_object_handlers = &reflection_object_handlers; + reflection_class_constant_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_extension_ptr = register_class_ReflectionExtension(reflector_ptr); reflection_extension_ptr->create_object = reflection_objects_new; reflection_extension_ptr->default_object_handlers = &reflection_object_handlers; + reflection_extension_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_zend_extension_ptr = register_class_ReflectionZendExtension(reflector_ptr); reflection_zend_extension_ptr->create_object = reflection_objects_new; reflection_zend_extension_ptr->default_object_handlers = &reflection_object_handlers; + reflection_zend_extension_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_reference_ptr = register_class_ReflectionReference(); reflection_reference_ptr->create_object = reflection_objects_new; reflection_reference_ptr->default_object_handlers = &reflection_object_handlers; + reflection_reference_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_attribute_ptr = register_class_ReflectionAttribute(reflector_ptr); reflection_attribute_ptr->create_object = reflection_objects_new; reflection_attribute_ptr->default_object_handlers = &reflection_object_handlers; + reflection_attribute_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr); reflection_enum_ptr->create_object = reflection_objects_new; reflection_enum_ptr->default_object_handlers = &reflection_object_handlers; + reflection_enum_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_enum_unit_case_ptr = register_class_ReflectionEnumUnitCase(reflection_class_constant_ptr); reflection_enum_unit_case_ptr->create_object = reflection_objects_new; reflection_enum_unit_case_ptr->default_object_handlers = &reflection_object_handlers; + reflection_enum_unit_case_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_enum_backed_case_ptr = register_class_ReflectionEnumBackedCase(reflection_enum_unit_case_ptr); reflection_enum_backed_case_ptr->create_object = reflection_objects_new; reflection_enum_backed_case_ptr->default_object_handlers = &reflection_object_handlers; + reflection_enum_backed_case_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_fiber_ptr = register_class_ReflectionFiber(); reflection_fiber_ptr->create_object = reflection_objects_new; reflection_fiber_ptr->default_object_handlers = &reflection_object_handlers; + reflection_fiber_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_constant_ptr = register_class_ReflectionConstant(reflector_ptr); reflection_constant_ptr->create_object = reflection_objects_new; reflection_constant_ptr->default_object_handlers = &reflection_object_handlers; + reflection_constant_ptr->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; reflection_property_hook_type_ptr = register_class_PropertyHookType(); diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index be511d7ee14cd..b33c27b2af2d1 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -432,6 +432,8 @@ public function getNamespaceName(): string {} public function getShortName(): string {} public function getAttributes(?string $name = null, int $flags = 0): array {} + + public function mayBeCyclic(): bool {} } class ReflectionObject extends ReflectionClass diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index d78a685dde9c9..7bc073f1f5459 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3c6be99bb36965139464925a618cb0bf03affa62 */ + * Stub hash: e2086e92426bd71218575f5a4c6dd0fea7049008 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -366,6 +366,8 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionClass_getAttributes arginfo_class_ReflectionFunctionAbstract_getAttributes +#define arginfo_class_ReflectionClass_mayBeCyclic arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType + ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionObject___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) ZEND_END_ARG_INFO() @@ -847,6 +849,7 @@ ZEND_METHOD(ReflectionClass, inNamespace); ZEND_METHOD(ReflectionClass, getNamespaceName); ZEND_METHOD(ReflectionClass, getShortName); ZEND_METHOD(ReflectionClass, getAttributes); +ZEND_METHOD(ReflectionClass, mayBeCyclic); ZEND_METHOD(ReflectionObject, __construct); ZEND_METHOD(ReflectionProperty, __construct); ZEND_METHOD(ReflectionProperty, __toString); @@ -1139,6 +1142,7 @@ static const zend_function_entry class_ReflectionClass_methods[] = { ZEND_ME(ReflectionClass, getNamespaceName, arginfo_class_ReflectionClass_getNamespaceName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionClass, getShortName, arginfo_class_ReflectionClass_getShortName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionClass, getAttributes, arginfo_class_ReflectionClass_getAttributes, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionClass, mayBeCyclic, arginfo_class_ReflectionClass_mayBeCyclic, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index a962028d30865..5a627b43324e5 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2654,6 +2654,7 @@ PHP_MINIT_FUNCTION(simplexml) ce_SimpleXMLElement = register_class_SimpleXMLElement(zend_ce_stringable, zend_ce_countable, spl_ce_RecursiveIterator); ce_SimpleXMLElement->create_object = sxe_object_new; ce_SimpleXMLElement->default_object_handlers = &sxe_object_handlers; + ce_SimpleXMLElement->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; ce_SimpleXMLElement->get_iterator = php_sxe_get_iterator; memcpy(&sxe_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 940b1621f75d0..e31cc7cf4b44c 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -455,6 +455,7 @@ static PHP_MINIT_FUNCTION(sockets) socket_ce = register_class_Socket(); socket_ce->create_object = socket_create_object; socket_ce->default_object_handlers = &socket_object_handlers; + socket_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&socket_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); socket_object_handlers.offset = XtOffsetOf(php_socket, std); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index af886944bc49e..a77f110c47e55 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1883,6 +1883,7 @@ PHP_MINIT_FUNCTION(spl_array) spl_ce_ArrayObject = register_class_ArrayObject(zend_ce_aggregate, zend_ce_arrayaccess, zend_ce_serializable, zend_ce_countable); spl_ce_ArrayObject->create_object = spl_array_object_new; spl_ce_ArrayObject->default_object_handlers = &spl_handler_ArrayObject; + spl_ce_ArrayObject->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&spl_handler_ArrayObject, &std_object_handlers, sizeof(zend_object_handlers)); @@ -1909,6 +1910,7 @@ PHP_MINIT_FUNCTION(spl_array) spl_ce_ArrayIterator = register_class_ArrayIterator(spl_ce_SeekableIterator, zend_ce_arrayaccess, zend_ce_serializable, zend_ce_countable); spl_ce_ArrayIterator->create_object = spl_array_object_new; spl_ce_ArrayIterator->default_object_handlers = &spl_handler_ArrayObject; + spl_ce_ArrayIterator->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator; spl_ce_RecursiveArrayIterator = register_class_RecursiveArrayIterator(spl_ce_ArrayIterator, spl_ce_RecursiveIterator); diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 5a78db2921a81..cf82c8000c450 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -1256,6 +1256,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ ); spl_ce_SplDoublyLinkedList->create_object = spl_dllist_object_new; spl_ce_SplDoublyLinkedList->default_object_handlers = &spl_handler_SplDoublyLinkedList; + spl_ce_SplDoublyLinkedList->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator; memcpy(&spl_handler_SplDoublyLinkedList, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 5d7949308a303..a25e389861cf1 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -964,6 +964,7 @@ PHP_MINIT_FUNCTION(spl_fixedarray) zend_ce_aggregate, zend_ce_arrayaccess, zend_ce_countable, php_json_serializable_ce); spl_ce_SplFixedArray->create_object = spl_fixedarray_new; spl_ce_SplFixedArray->default_object_handlers = &spl_handler_SplFixedArray; + spl_ce_SplFixedArray->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_SplFixedArray->get_iterator = spl_fixedarray_get_iterator; memcpy(&spl_handler_SplFixedArray, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index d4450da42009c..52d5c9783a074 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -1141,6 +1141,7 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ spl_ce_SplHeap = register_class_SplHeap(zend_ce_iterator, zend_ce_countable); spl_ce_SplHeap->create_object = spl_heap_object_new; spl_ce_SplHeap->default_object_handlers = &spl_handler_SplHeap; + spl_ce_SplHeap->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_SplHeap->get_iterator = spl_heap_get_iterator; memcpy(&spl_handler_SplHeap, &std_object_handlers, sizeof(zend_object_handlers)); @@ -1162,6 +1163,7 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ spl_ce_SplPriorityQueue = register_class_SplPriorityQueue(zend_ce_iterator, zend_ce_countable); spl_ce_SplPriorityQueue->create_object = spl_heap_object_new; spl_ce_SplPriorityQueue->default_object_handlers = &spl_handler_SplPriorityQueue; + spl_ce_SplPriorityQueue->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_SplPriorityQueue->get_iterator = spl_pqueue_get_iterator; memcpy(&spl_handler_SplPriorityQueue, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index d4e40bf6b684a..a0360ef556d62 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -3108,6 +3108,7 @@ PHP_MINIT_FUNCTION(spl_iterators) spl_ce_RecursiveIteratorIterator = register_class_RecursiveIteratorIterator(spl_ce_OuterIterator); spl_ce_RecursiveIteratorIterator->create_object = spl_RecursiveIteratorIterator_new; spl_ce_RecursiveIteratorIterator->default_object_handlers = &spl_handlers_rec_it_it; + spl_ce_RecursiveIteratorIterator->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator; memcpy(&spl_handlers_rec_it_it, &std_object_handlers, sizeof(zend_object_handlers)); @@ -3127,6 +3128,7 @@ PHP_MINIT_FUNCTION(spl_iterators) spl_ce_IteratorIterator = register_class_IteratorIterator(spl_ce_OuterIterator); spl_ce_IteratorIterator->create_object = spl_dual_it_new; spl_ce_IteratorIterator->default_object_handlers = &spl_handlers_dual_it; + spl_ce_IteratorIterator->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; spl_ce_FilterIterator = register_class_FilterIterator(spl_ce_IteratorIterator); spl_ce_FilterIterator->create_object = spl_dual_it_new; diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 5222fe2a7fa4d..a3847bed048e8 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1379,6 +1379,7 @@ PHP_MINIT_FUNCTION(spl_observer) spl_ce_SplObjectStorage = register_class_SplObjectStorage(zend_ce_countable, spl_ce_SeekableIterator, zend_ce_serializable, zend_ce_arrayaccess); spl_ce_SplObjectStorage->create_object = spl_SplObjectStorage_new; spl_ce_SplObjectStorage->default_object_handlers = &spl_handler_SplObjectStorage; + spl_ce_SplObjectStorage->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&spl_handler_SplObjectStorage, &std_object_handlers, sizeof(zend_object_handlers)); @@ -1395,6 +1396,7 @@ PHP_MINIT_FUNCTION(spl_observer) spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator); spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new; spl_ce_MultipleIterator->default_object_handlers = &spl_handler_SplObjectStorage; + spl_ce_MultipleIterator->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; return SUCCESS; } diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 01b8af435b633..e7200b65355cd 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -2411,6 +2411,7 @@ PHP_MINIT_FUNCTION(sqlite3) php_sqlite3_sc_entry = register_class_SQLite3(); php_sqlite3_sc_entry->create_object = php_sqlite3_object_new; php_sqlite3_sc_entry->default_object_handlers = &sqlite3_object_handlers; + php_sqlite3_sc_entry->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; /* Register SQLite 3 Prepared Statement Class */ sqlite3_stmt_object_handlers.offset = XtOffsetOf(php_sqlite3_stmt, zo); diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 7eca5c0795e2a..d034898f861c9 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -228,6 +228,7 @@ PHP_MINIT_FUNCTION(xml) xml_parser_ce = register_class_XMLParser(); xml_parser_ce->create_object = xml_parser_create_object; xml_parser_ce->default_object_handlers = &xml_parser_object_handlers; + xml_parser_ce->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; memcpy(&xml_parser_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); xml_parser_object_handlers.offset = XtOffsetOf(xml_parser, std); diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c index dec7eb501eb2f..8c45429269d72 100644 --- a/ext/xsl/php_xsl.c +++ b/ext/xsl/php_xsl.c @@ -278,6 +278,7 @@ PHP_MINIT_FUNCTION(xsl) xsl_xsltprocessor_class_entry = register_class_XSLTProcessor(); xsl_xsltprocessor_class_entry->create_object = xsl_objects_new; xsl_xsltprocessor_class_entry->default_object_handlers = &xsl_object_handlers; + xsl_xsltprocessor_class_entry->ce_flags |= ZEND_ACC_MAY_BE_CYCLIC; #ifdef HAVE_XSL_EXSLT exsltRegisterAll();