@@ -797,16 +797,28 @@ HashTable *zend_lazy_object_get_gc(zend_object *zobj, zval **table, int *n)
797797 }
798798 zend_get_gc_buffer_add_zval (gc_buffer , & info -> u .initializer .zv );
799799
800- /* Uninitialized lazy objects can not have dynamic properties, so we can
801- * ignore zobj->properties. */
802- zval * prop = zobj -> properties_table ;
803- zval * end = prop + zobj -> ce -> default_properties_count ;
804- for ( ; prop < end ; prop ++ ) {
805- zend_get_gc_buffer_add_zval (gc_buffer , prop );
800+ /* Lazy objects may have a properties ht in two cases:
801+ * - After fetching debug infos
802+ * - After lazy init failed in zend_std_get_properties()
803+ *
804+ * In the latter case zobj->properties is an empty ht. We should ignore it,
805+ * otherwise we may mask references to the GC. In the former case we must
806+ * return it, otherwise the GC may traverse properties twice in case the ht
807+ * it a root by itself. */
808+ zend_array * ht ;
809+ if (zobj -> properties && zend_hash_num_elements (zobj -> properties ) > 0 ) {
810+ ht = zobj -> properties ;
811+ } else {
812+ zval * prop = zobj -> properties_table ;
813+ zval * end = prop + zobj -> ce -> default_properties_count ;
814+ for ( ; prop < end ; prop ++ ) {
815+ zend_get_gc_buffer_add_zval (gc_buffer , prop );
816+ }
817+ ht = NULL ;
806818 }
807819
808820 zend_get_gc_buffer_use (gc_buffer , table , n );
809- return NULL ;
821+ return ht ;
810822}
811823
812824zend_property_info * zend_lazy_object_get_property_info_for_slot (zend_object * obj , zval * slot )
0 commit comments