summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2016-11-02 12:11:30 +0800
committerXinchen Hui <laruence@gmail.com>2016-11-02 12:11:30 +0800
commit1efb9fd32d2618bd603e3bc4dc9adb45d509cada (patch)
treedc6389c7ee6b7f4d4a6ab96998ba3ccc10a927b1
parent8957ff36b38a560cfa9a2a3f2a1271cfb2fcbeb9 (diff)
downloadphp-git-1efb9fd32d2618bd603e3bc4dc9adb45d509cada.tar.gz
Fixed bug #73423 (Reproducible crash with GDB backtrace)
-rw-r--r--NEWS3
-rw-r--r--ext/spl/spl_iterators.c14
-rw-r--r--ext/spl/tests/bug73423.phpt71
3 files changed, 84 insertions, 4 deletions
diff --git a/NEWS b/NEWS
index a0c5152bd5..ac4d958c9a 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,9 @@ PHP NEWS
. Fixed bug #73392 (A use-after-free in zend allocator management).
(Laruence)
+- SPL:
+ . Fixed bug #73423 (Reproducible crash with GDB backtrace). (Laruence)
+
10 Nov 2016 PHP 7.0.13
- Core:
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 6708689d05..cc784df937 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -175,9 +175,12 @@ static void spl_recursive_it_dtor(zend_object_iterator *_iter)
zend_object_iterator *sub_iter;
while (object->level > 0) {
- sub_iter = object->iterators[object->level].iterator;
- zend_iterator_dtor(sub_iter);
- zval_ptr_dtor(&object->iterators[object->level--].zobject);
+ 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->iterators = erealloc(object->iterators, sizeof(spl_sub_iterator));
object->level = 0;
@@ -391,8 +394,11 @@ next_step:
}
}
if (object->level > 0) {
+ zval garbage;
+ ZVAL_COPY_VALUE(&garbage, &object->iterators[object->level].zobject);
+ ZVAL_UNDEF(&object->iterators[object->level].zobject);
+ zval_ptr_dtor(&garbage);
zend_iterator_dtor(iterator);
- zval_ptr_dtor(&object->iterators[object->level].zobject);
object->level--;
}
} else {
diff --git a/ext/spl/tests/bug73423.phpt b/ext/spl/tests/bug73423.phpt
new file mode 100644
index 0000000000..58e1acb822
--- /dev/null
+++ b/ext/spl/tests/bug73423.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Bug #73423 (Reproducible crash with GDB backtrace)
+--FILE--
+<?php
+
+class foo implements \RecursiveIterator
+ {
+ public $foo = [];
+
+ public Function current ()
+ {
+ return current ($this->foo);
+ }
+
+ public Function key ()
+ {
+ return key ($this->foo);
+ }
+
+ public Function next ()
+ {
+ next ($this->foo);
+ }
+
+ public Function rewind ()
+ {
+ reset ($this->foo);
+ }
+
+ public Function valid ()
+ {
+ return current ($this->foo) !== false;
+ }
+
+ public Function getChildren ()
+ {
+ return current ($this->foo);
+ }
+
+ public Function hasChildren ()
+ {
+ return (bool) count ($this->foo);
+ }
+ }
+
+
+class fooIterator extends \RecursiveFilterIterator
+ {
+ public Function __destruct ()
+ {
+ eval("class A extends NotExists {}");
+
+ /* CRASH */
+ }
+
+ public Function accept ()
+ {
+ return true;
+ }
+ }
+
+
+$foo = new foo ();
+
+$foo->foo[] = new foo ();
+
+foreach (new \RecursiveIteratorIterator (new fooIterator ($foo)) as $bar) ;
+
+?>
+--EXPECTF--
+Fatal error: Class 'NotExists' not found in %sbug73423.php(%d) : eval()'d code on line 1