@@ -32,27 +32,38 @@ extern "C" {
3232zend_class_entry *IntlIterator_ce_ptr;
3333zend_object_handlers IntlIterator_handlers;
3434
35+ static  void  zoi_with_current_destroy_self (zend_object_iterator *iter, zoi_with_current *zoiwc)
36+ {
37+ 	/*  Object not here anymore (we've been called by the object free handler)
38+ 	 * Note that the iterator wrapper objects (that also depend on this 
39+ 	 * structure) call this function earlier, in the destruction phase, which 
40+ 	 * precedes the object free phase. Therefore there's no risk on this 
41+ 	 * function being called by the iterator wrapper destructor function and 
42+ 	 * not finding the memory of this iterator allocated anymore. */  
43+ 	iter->funcs ->invalidate_current (iter);
44+ 	zoiwc->destroy_it (iter);
45+ }
46+ 
3547void  zoi_with_current_dtor (zend_object_iterator *iter)
3648{
3749	zoi_with_current *zoiwc = (zoi_with_current*)iter;
3850
3951	if  (!Z_ISUNDEF (zoiwc->wrapping_obj )) {
4052		/*  we have to copy the pointer because zoiwc->wrapping_obj may be
41- 		  * changed midway the execution of zval_ptr_dtor() */  
53+ 		* changed midway the execution of zval_ptr_dtor() */  
4254		zval *zwo = &zoiwc->wrapping_obj ;
4355
4456		/*  object is still here, we can rely on it to call this again and
4557		 * destroy this object */  
4658		zval_ptr_dtor (zwo);
59+ 
60+ 		/*  We may only invalidate and destroy if this was actually the last instance.
61+ 		 * If it was, then IntlIterator_objects_free() will have set zwo to UNDEF. */  
62+ 		if  (Z_ISUNDEF_P (zwo)) {
63+ 			zoi_with_current_destroy_self (iter, zoiwc);
64+ 		}
4765	} else  {
48- 		/*  Object not here anymore (we've been called by the object free handler)
49- 		 * Note that the iterator wrapper objects (that also depend on this 
50- 		 * structure) call this function earlier, in the destruction phase, which 
51- 		 * precedes the object free phase. Therefore there's no risk on this 
52- 		 * function being called by the iterator wrapper destructor function and 
53- 		 * not finding the memory of this iterator allocated anymore. */  
54- 		iter->funcs ->invalidate_current (iter);
55- 		zoiwc->destroy_it (iter);
66+ 		zoi_with_current_destroy_self (iter, zoiwc);
5667	}
5768}
5869
@@ -126,6 +137,16 @@ static void string_enum_destroy_it(zend_object_iterator *iter)
126137	delete  (StringEnumeration*)Z_PTR (iter->data );
127138}
128139
140+ static  HashTable *string_enum_get_gc (zend_object_iterator *object, zval **table, int  *n)
141+ {
142+ 	zoi_with_current *zoiwc = (zoi_with_current *) object;
143+ 
144+ 	*table = &zoiwc->wrapping_obj ;
145+ 	*n = 1 ;
146+ 
147+ 	return  NULL ;
148+ }
149+ 
129150static  const  zend_object_iterator_funcs string_enum_object_iterator_funcs = {
130151	zoi_with_current_dtor,
131152	zoi_with_current_valid,
@@ -134,7 +155,7 @@ static const zend_object_iterator_funcs string_enum_object_iterator_funcs = {
134155	string_enum_current_move_forward,
135156	string_enum_rewind,
136157	zoi_with_current_invalidate_current,
137- 	NULL ,  /*  get_gc  */ 
158+ 	string_enum_get_gc, 
138159};
139160
140161U_CFUNC void  IntlIterator_from_StringEnumeration (StringEnumeration *se, zval *object)
@@ -148,7 +169,8 @@ U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *ob
148169	ii->iterator ->funcs  = &string_enum_object_iterator_funcs;
149170	ii->iterator ->index  = 0 ;
150171	((zoi_with_current*)ii->iterator )->destroy_it  = string_enum_destroy_it;
151- 	ZVAL_OBJ (&((zoi_with_current*)ii->iterator )->wrapping_obj , Z_OBJ_P (object));
172+ 	/*  This iterator holds a reference to the object, the object may not disappear */ 
173+ 	ZVAL_OBJ_COPY (&((zoi_with_current*)ii->iterator )->wrapping_obj , Z_OBJ_P (object));
152174	ZVAL_UNDEF (&((zoi_with_current*)ii->iterator )->current );
153175}
154176
@@ -158,6 +180,7 @@ static void IntlIterator_objects_free(zend_object *object)
158180
159181	if  (ii->iterator ) {
160182		zval *wrapping_objp = &((zoi_with_current*)ii->iterator )->wrapping_obj ;
183+ 		/*  Signal that it was the last reference that got destroyed */ 
161184		ZVAL_UNDEF (wrapping_objp);
162185		zend_iterator_dtor (ii->iterator );
163186	}
@@ -166,6 +189,22 @@ static void IntlIterator_objects_free(zend_object *object)
166189	zend_object_std_dtor (&ii->zo );
167190}
168191
192+ static  HashTable *IntlIterator_get_gc (zend_object *object, zval **table, int  *n)
193+ {
194+ 	IntlIterator_object *ii = php_intl_iterator_fetch_object (object);
195+ 
196+ 	if  (ii->iterator ) {
197+ 		zend_get_gc_buffer *gc = zend_get_gc_buffer_create ();
198+ 		zend_get_gc_buffer_add_obj (gc, &ii->iterator ->std );
199+ 		zend_get_gc_buffer_use (gc, table, n);
200+ 	} else  {
201+ 		*table = NULL ;
202+ 		*n = 0 ;
203+ 	}
204+ 
205+ 	return  NULL ;
206+ }
207+ 
169208static  zend_object_iterator *IntlIterator_get_iterator (
170209	zend_class_entry *ce, zval *object, int  by_ref)
171210{
@@ -298,5 +337,5 @@ U_CFUNC void intl_register_IntlIterator_class(void)
298337	IntlIterator_handlers.offset  = XtOffsetOf (IntlIterator_object, zo);
299338	IntlIterator_handlers.clone_obj  = NULL ;
300339	IntlIterator_handlers.free_obj  = IntlIterator_objects_free;
301- 
340+ 	IntlIterator_handlers. get_gc  = IntlIterator_get_gc; 
302341}
0 commit comments