]> granicus.if.org Git - php/commitdiff
Fix leak when breaking out of FilesystemIterator
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 15 Feb 2021 09:36:48 +0000 (10:36 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 15 Feb 2021 09:37:59 +0000 (10:37 +0100)
We need to always destroy current, not just when iter.data is not
set.

Take this opportunity to clean up the iterator destructor code a
bit, to remove redundant checks and incorrect comments.

ext/spl/spl_directory.c
ext/spl/tests/filesystemiterator_leak.phpt [new file with mode: 0644]

index 6fec6d2e25d327877249bd7f1cb39f6c2cad8820..daed72d847089d610fd7bcc4ef3cf2cb363a3473 100644 (file)
@@ -1677,15 +1677,7 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval
 static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
 {
        spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
-
-       if (!Z_ISUNDEF(iterator->intern.data)) {
-               zval *object = &iterator->intern.data;
-               zval_ptr_dtor(object);
-       }
-       /* Otherwise we were called from the owning object free storage handler as
-        * it sets iterator->intern.data to IS_UNDEF.
-        * We don't even need to destroy iterator->current as we didn't add a
-        * reference to it in move_forward or get_iterator */
+       zval_ptr_dtor(&iterator->intern.data);
 }
 /* }}} */
 
@@ -1747,16 +1739,8 @@ static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
 static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
 {
        spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
-
-       if (!Z_ISUNDEF(iterator->intern.data)) {
-               zval *object = &iterator->intern.data;
-               zval_ptr_dtor(object);
-       } else {
-               if (!Z_ISUNDEF(iterator->current)) {
-                       zval_ptr_dtor(&iterator->current);
-                       ZVAL_UNDEF(&iterator->current);
-               }
-       }
+       zval_ptr_dtor(&iterator->intern.data);
+       zval_ptr_dtor(&iterator->current);
 }
 /* }}} */
 
diff --git a/ext/spl/tests/filesystemiterator_leak.phpt b/ext/spl/tests/filesystemiterator_leak.phpt
new file mode 100644 (file)
index 0000000..9cdaeaa
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Don't leak when breaking from FilesystemIterator
+--FILE--
+<?php
+$iterator = new FilesystemIterator(__DIR__);
+foreach ($iterator as $value) {
+    break;
+}
+?>
+===DONE===
+--EXPECT--
+===DONE===