Skip to content

Commit

Permalink
Handle out of order destruction of RecursiveIteratorIterator
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Jul 2, 2021
1 parent 29b8269 commit f7b1238
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 8 deletions.
19 changes: 11 additions & 8 deletions ext/spl/spl_iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,18 @@ static void spl_recursive_it_dtor(zend_object_iterator *_iter)
spl_recursive_it_object *object = Z_SPLRECURSIVE_IT_P(&iter->intern.data);
zend_object_iterator *sub_iter;

while (object->level > 0) {
if (!Z_ISUNDEF(object->iterators[object->level].zobject)) {
sub_iter = object->iterators[object->level].iterator;
zend_iterator_dtor(sub_iter);
zval_ptr_dtor(&object->iterators[object->level].zobject);
if (object->iterators) {
while (object->level > 0) {
if (!Z_ISUNDEF(object->iterators[object->level].zobject)) {
sub_iter = object->iterators[object->level].iterator;
zend_iterator_dtor(sub_iter);
zval_ptr_dtor(&object->iterators[object->level].zobject);
}
object->level--;
}
object->level--;
object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
object->level = 0;
}
object->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
object->level = 0;

zval_ptr_dtor(&iter->intern.data);
}
Expand Down Expand Up @@ -905,6 +907,7 @@ static void spl_RecursiveIteratorIterator_free_storage(zend_object *_object)
object->level--;
}
efree(object->iterators);
object->iterators = NULL;
}

zend_object_std_dtor(&object->std);
Expand Down
14 changes: 14 additions & 0 deletions ext/spl/tests/RecursiveIteratorIterator_dtor_order.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
Handle object_iterator being destroyed before the RecursiveIteratorIterator object
--FILE--
<?php

$dummy = new stdClass; // Dummy object to control object store ordering
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator([1]));
unset($dummy);
foreach ($it as $v) {
eval('class self {}'); // Cause a bailout.
}
?>
--EXPECTF--
Fatal error: Cannot use 'self' as class name as it is reserved in %s on line %d

0 comments on commit f7b1238

Please sign in to comment.