From d4d0852c2363fae2c7f979169ed8621379411a2c Mon Sep 17 00:00:00 2001 From: Alex Dowad Date: Thu, 23 Apr 2020 10:45:20 +0200 Subject: SplDoublyLinkedList uses iteration flags in iterator struct The 'flags' field in spl_dllist_it was formerly unused. This means that if one started to iterate over an SplDoublyLinkedList using 'foreach', and then *changed* the iteration mode halfway, the 'foreach' loop would start iterating in the opposite direction. Probably this was not what was intended. Therefore, use the 'flags' field in spl_dllist_it for iteration via 'foreach'. For explicit iteration using methods like '::next()' and '::current()', continue to use the flags in the SplDoublyLinkedList object itself. --- ext/spl/spl_dllist.c | 4 +-- ...lDoublyLinkedList_consistent_iterator_mode.phpt | 39 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 7dbc3699d0..b11cfacc3c 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -964,7 +964,7 @@ static void spl_dllist_it_rewind(zend_object_iterator *iter) /* {{{ */ spl_dllist_object *object = Z_SPLDLLIST_P(&iter->data); spl_ptr_llist *llist = object->llist; - spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags); + spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, iterator->flags); } /* }}} */ @@ -1005,7 +1005,7 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter) /* {{{ */ zend_user_it_invalidate_current(iter); - spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags); + spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, iterator->flags); } /* }}} */ diff --git a/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt b/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt new file mode 100644 index 0000000000..fa901dda91 --- /dev/null +++ b/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt @@ -0,0 +1,39 @@ +--TEST-- +Iteration over SplDoublyLinkedList via 'foreach' does not change direction partway +--FILE-- +push(1); +$list->push(2); +$list->push(3); + +/* SplDoublyLinkedList would previously check the iteration mode *each time* + it would advance to the next item in a 'foreach' loop + This meant that it could move forward, then backward, then forward if the + iteration mode was changed in the middle of a loop */ + +$list->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO); +foreach ($list as $item) { + $list->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO); + echo $item, "\n"; +} + +echo "***\n"; + +$list->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO); +foreach ($list as $item) { + $list->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO); + echo $item, "\n"; +} + + +?> +--EXPECT-- +1 +2 +3 +*** +3 +2 +1 -- cgit v1.2.1