Skip to content

Commit c9ffae1

Browse files
dstogovnikic
authored andcommitted
Fixed bug #77633
Add a new class flag to inherit get_iterator() when implementing the Iterator/IteratorAggregate interfaces and use it for ArrayIterator.
1 parent 7d0d94e commit c9ffae1

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

Zend/zend_compile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ typedef struct _zend_oparray_context {
263263
/* Whether all property types are resolved to CEs | | | */
264264
#define ZEND_ACC_PROPERTY_TYPES_RESOLVED (1 << 16) /* X | | | */
265265
/* | | | */
266+
/* Children must reuse parent get_iterator() | | | */
267+
#define ZEND_ACC_REUSE_GET_ITERATOR (1 << 17) /* X | | | */
268+
/* | | | */
266269
/* Function Flags (unused: 28...30) | | | */
267270
/* ============== | | | */
268271
/* | | | */

Zend/zend_interfaces.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,13 @@ static int zend_implement_aggregate(zend_class_entry *interface, zend_class_entr
340340
}
341341
}
342342
}
343-
class_type->get_iterator = zend_user_it_get_new_iterator;
343+
if (class_type->parent
344+
&& (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
345+
class_type->get_iterator = class_type->parent->get_iterator;
346+
class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
347+
} else {
348+
class_type->get_iterator = zend_user_it_get_new_iterator;
349+
}
344350
funcs_ptr = class_type->iterator_funcs_ptr;
345351
if (class_type->type == ZEND_INTERNAL_CLASS) {
346352
if (!funcs_ptr) {
@@ -381,7 +387,13 @@ static int zend_implement_iterator(zend_class_entry *interface, zend_class_entry
381387
return FAILURE;
382388
}
383389
}
384-
class_type->get_iterator = zend_user_it_get_iterator;
390+
if (class_type->parent
391+
&& (class_type->parent->ce_flags & ZEND_ACC_REUSE_GET_ITERATOR)) {
392+
class_type->get_iterator = class_type->parent->get_iterator;
393+
class_type->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
394+
} else {
395+
class_type->get_iterator = zend_user_it_get_iterator;
396+
}
385397
funcs_ptr = class_type->iterator_funcs_ptr;
386398
if (class_type->type == ZEND_INTERNAL_CLASS) {
387399
if (!funcs_ptr) {

ext/spl/spl_array.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *
206206
while (parent) {
207207
if (parent == spl_ce_ArrayIterator || parent == spl_ce_RecursiveArrayIterator) {
208208
intern->std.handlers = &spl_handler_ArrayIterator;
209-
class_type->get_iterator = spl_array_get_iterator;
210209
break;
211210
} else if (parent == spl_ce_ArrayObject) {
212211
intern->std.handlers = &spl_handler_ArrayObject;
@@ -1969,6 +1968,8 @@ PHP_MINIT_FUNCTION(spl_array)
19691968
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Countable);
19701969
memcpy(&spl_handler_ArrayIterator, &spl_handler_ArrayObject, sizeof(zend_object_handlers));
19711970
spl_ce_ArrayIterator->get_iterator = spl_array_get_iterator;
1971+
spl_ce_ArrayIterator->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
1972+
19721973

19731974
REGISTER_SPL_CLASS_CONST_LONG(ArrayObject, "STD_PROP_LIST", SPL_ARRAY_STD_PROP_LIST);
19741975
REGISTER_SPL_CLASS_CONST_LONG(ArrayObject, "ARRAY_AS_PROPS", SPL_ARRAY_ARRAY_AS_PROPS);
@@ -1979,6 +1980,7 @@ PHP_MINIT_FUNCTION(spl_array)
19791980
REGISTER_SPL_SUB_CLASS_EX(RecursiveArrayIterator, ArrayIterator, spl_array_object_new, spl_funcs_RecursiveArrayIterator);
19801981
REGISTER_SPL_IMPLEMENTS(RecursiveArrayIterator, RecursiveIterator);
19811982
spl_ce_RecursiveArrayIterator->get_iterator = spl_array_get_iterator;
1983+
spl_ce_RecursiveArrayIterator->ce_flags |= ZEND_ACC_REUSE_GET_ITERATOR;
19821984

19831985
REGISTER_SPL_CLASS_CONST_LONG(RecursiveArrayIterator, "CHILD_ARRAYS_ONLY", SPL_ARRAY_CHILD_ARRAYS_ONLY);
19841986

0 commit comments

Comments
 (0)