Skip to content

Commit 2f08950

Browse files
committed
test
1 parent 8c2c694 commit 2f08950

File tree

4 files changed

+56
-15
lines changed

4 files changed

+56
-15
lines changed

Zend/zend_vm_def.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -3153,7 +3153,8 @@ ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY)
31533153
if (Z_FE_ITER_P(var) != (uint32_t)-1) {
31543154
zend_hash_iterator_del(Z_FE_ITER_P(var));
31553155
}
3156-
zval_ptr_dtor_nogc(var);
3156+
//zval_ptr_dtor_nogc(var);
3157+
zval_ptr_dtor(var);
31573158
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
31583159
}
31593160

Zend/zend_vm_execute.h

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/intl/breakiterator/breakiterator_iterators.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ U_CFUNC zend_object_iterator *_breakiterator_get_iterator(
115115
zoi_iter->zoi.funcs = &breakiterator_iterator_funcs;
116116
zoi_iter->zoi.index = 0;
117117
zoi_iter->destroy_it = _breakiterator_destroy_it;
118-
ZVAL_UNDEF(&zoi_iter->wrapping_obj); /* not used; object is in zoi.data */
119118
ZVAL_UNDEF(&zoi_iter->current);
120119

121120
return reinterpret_cast<zend_object_iterator *>(zoi_iter);
@@ -231,7 +230,7 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv,
231230
ii->iterator->index = 0;
232231

233232
((zoi_with_current*)ii->iterator)->destroy_it = _breakiterator_parts_destroy_it;
234-
ZVAL_OBJ(&((zoi_with_current*)ii->iterator)->wrapping_obj, Z_OBJ_P(object));
233+
ZVAL_UNDEF(&((zoi_with_current*)ii->iterator)->wrapping_obj); /* not used; object is in zoi.data */
235234
ZVAL_UNDEF(&((zoi_with_current*)ii->iterator)->current);
236235

237236
((zoi_break_iter_parts*)ii->iterator)->bio = Z_INTL_BREAKITERATOR_P(break_iter_zv);

ext/intl/common/common_enum.cpp

+51-11
Original file line numberDiff line numberDiff line change
@@ -32,27 +32,38 @@ extern "C" {
3232
zend_class_entry *IntlIterator_ce_ptr;
3333
zend_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+
3547
void 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+
129150
static 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

140161
U_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+
169208
static zend_object_iterator *IntlIterator_get_iterator(
170209
zend_class_entry *ce, zval *object, int by_ref)
171210
{
@@ -293,6 +332,7 @@ U_CFUNC void intl_register_common_symbols(int module_number)
293332
IntlIterator_handlers.offset = XtOffsetOf(IntlIterator_object, zo);
294333
IntlIterator_handlers.clone_obj = NULL;
295334
IntlIterator_handlers.free_obj = IntlIterator_objects_free;
335+
IntlIterator_handlers.get_gc = IntlIterator_get_gc;
296336

297337
register_common_symbols(module_number);
298338
}

0 commit comments

Comments
 (0)