summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorGustavo André dos Santos Lopes <cataphract@php.net>2012-03-18 15:07:20 +0000
committerGustavo André dos Santos Lopes <cataphract@php.net>2012-03-18 15:07:20 +0000
commit714f1ff4b37c5101b3c61ea108a3d415f41e50df (patch)
tree1d458e961020452dda0eab6e5c107236de4efd60 /ext
parentef19fba2d59bc0e7875342d01cd513ae7f4c5d5e (diff)
downloadphp-git-714f1ff4b37c5101b3c61ea108a3d415f41e50df.tar.gz
- 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).
Diffstat (limited to 'ext')
-rwxr-xr-xext/spl/spl_directory.c47
-rw-r--r--ext/spl/tests/bug61418.phpt23
2 files changed, 55 insertions, 15 deletions
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index f0e903f0bf..fb198236e5 100755
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -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
index 0000000000..c5d9db9484
--- /dev/null
+++ b/ext/spl/tests/bug61418.phpt
@@ -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==