]> granicus.if.org Git - php/commitdiff
- Fixed bug #61418 (Segmentation fault when DirectoryIterator's or
authorGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 18 Mar 2012 15:07:20 +0000 (15:07 +0000)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 18 Mar 2012 15:07:20 +0000 (15:07 +0000)
  FilesystemIterator's iterators are requested more than once without
  having had its dtor callback called in between).

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

diff --git a/NEWS b/NEWS
index 04bcd32def63426d840b7dd4bb72c41791d89a42..7f81598b169d9546b4b2852d103043592690cedc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -81,6 +81,9 @@ PHP                                                                        NEWS
 
 - SPL
   . Fixed memory leak when calling SplFileInfo's constructor twice. (Felipe)
+  . Fixed bug #61418 (Segmentation fault when DirectoryIterator's or
+    FilesystemIterator's iterators are requested more than once without
+    having had its dtor callback called in between). (Gustavo)
   . Fixed bug #61347 (inconsistent isset behavior of Arrayobject). (Laruence)
   . Fixed bug #61326 (ArrayObject comparison). (Gustavo)
 
index f0e903f0bf57b0426c461d69f3dd1a1ebcd6022f..fb198236e5ef341b981c2fbefd538546d6aeb2d8 100755 (executable)
@@ -120,6 +120,16 @@ static void spl_filesystem_object_free_storage(void *object TSRMLS_DC) /* {{{ */
                spl_filesystem_file_free_line(intern TSRMLS_CC);
                break;
        }
+
+       {
+               zend_object_iterator *iterator;
+               iterator = (zend_object_iterator*)
+                               spl_filesystem_object_to_iterator(intern);
+               if (iterator->data != NULL) {
+                       iterator->data = NULL;
+                       iterator->funcs->dtor(iterator TSRMLS_CC);
+               }
+       }
        efree(object);
 } /* }}} */
 
@@ -1627,10 +1637,15 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval
        dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
        iterator   = spl_filesystem_object_to_iterator(dir_object);
 
-       Z_SET_REFCOUNT_P(object, Z_REFCOUNT_P(object) + 2);
-       iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
-       iterator->current = object;
+       /* initialize iterator if it wasn't gotten before */
+       if (iterator->intern.data == NULL) {
+               iterator->intern.data = object;
+               iterator->intern.funcs = &spl_filesystem_dir_it_funcs;
+               /* ->current must be initialized; rewind doesn't set it and valid
+                * doesn't check whether it's set */
+               iterator->current = object;
+       }
+       zval_add_ref(&object);
        
        return (zend_object_iterator*)iterator;
 }
@@ -1709,15 +1724,15 @@ static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter TSRMLS_DC)
 static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter TSRMLS_DC)
 {
        spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
-       zval *zfree = (zval*)iterator->intern.data;
 
-       if (iterator->current) {
-               zval_ptr_dtor(&iterator->current);
+       if (iterator->intern.data) {
+               zval *object =  iterator->intern.data;
+               zval_ptr_dtor(&object);
+       } else {
+               if (iterator->current) {
+                       zval_ptr_dtor(&iterator->current);
+               }
        }
-       iterator->intern.data = NULL; /* mark as unused */
-       /* free twice as we add ref twice */
-       zval_ptr_dtor(&zfree);
-       zval_ptr_dtor(&zfree);
 }
 /* }}} */
 
@@ -1828,10 +1843,12 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva
        dir_object = (spl_filesystem_object*)zend_object_store_get_object(object TSRMLS_CC);
        iterator   = spl_filesystem_object_to_iterator(dir_object);
 
-       Z_SET_REFCOUNT_P(object, Z_REFCOUNT_P(object) + 2);
-       iterator->intern.data = (void*)object;
-       iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
-       iterator->current = NULL;
+       /* initialize iterator if wasn't gotten before */
+       if (iterator->intern.data == NULL) {
+               iterator->intern.data = object;
+               iterator->intern.funcs = &spl_filesystem_tree_it_funcs;
+       }
+       zval_add_ref(&object);
        
        return (zend_object_iterator*)iterator;
 }
diff --git a/ext/spl/tests/bug61418.phpt b/ext/spl/tests/bug61418.phpt
new file mode 100644 (file)
index 0000000..c5d9db9
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Bug #61418: Segmentation fault using FiltesystemIterator & RegexIterator
+--FILE--
+<?php
+$fileIterator = new FilesystemIterator(__DIR__, FilesystemIterator::KEY_AS_FILENAME);
+$regexpIterator = new RegexIterator($fileIterator, '#.*#');
+foreach ($fileIterator as $key => $file)
+{
+}
+unset($regexpIterator);
+unset($fileIterator);
+
+$dirIterator = new DirectoryIterator(__DIR__);
+$regexpIterator2 = new RegexIterator($dirIterator, '#.*#');
+foreach ($dirIterator as $key => $file)
+{
+}
+unset($regexpIterator2);
+unset($dirIterator);
+?>
+==DONE==
+--EXPECT--
+==DONE==