]> granicus.if.org Git - php/commitdiff
Fixed bug #79151
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 23 Jan 2020 13:19:20 +0000 (14:19 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 23 Jan 2020 13:20:26 +0000 (14:20 +0100)
Make sure we also NULL out next/prev of the removed element on
pop/shift. This only matter is that element is still being referenced
by an iterator.

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

diff --git a/NEWS b/NEWS
index bbb3c919d1d7723fdaae793a030407b0b41fdfea..20efc78daa93b4199b586fb7e70000cf84bcd0dd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ PHP                                                                        NEWS
   . Fixed bug #79115 (ReflectionClass::isCloneable call reflected class
     __destruct). (Nikita)
 
+- SPL:
+  . Fixed bug #79151 (heap use after free caused by
+    spl_dllist_it_helper_move_forward). (Nikita)
+
 23 Jan 2020, PHP 7.3.14
 
 - Core
index 10e104270cbcdf0ec16fdaf4dd47445ef5c31458..ba9488abfc226768609573cf49f8ce2908110edd 100644 (file)
@@ -257,6 +257,7 @@ static void spl_ptr_llist_pop(spl_ptr_llist *llist, zval *ret) /* {{{ */
        llist->count--;
        ZVAL_COPY(ret, &tail->data);
 
+       tail->prev = NULL;
        if (llist->dtor) {
                llist->dtor(tail);
        }
@@ -310,6 +311,7 @@ static void spl_ptr_llist_shift(spl_ptr_llist *llist, zval *ret) /* {{{ */
        llist->count--;
        ZVAL_COPY(ret, &head->data);
 
+       head->next = NULL;
        if (llist->dtor) {
                llist->dtor(head);
        }
diff --git a/ext/spl/tests/bug79151.phpt b/ext/spl/tests/bug79151.phpt
new file mode 100644 (file)
index 0000000..ec4fac8
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug #79151: heap use after free caused by spl_dllist_it_helper_move_forward
+--FILE--
+<?php
+
+$a = new SplDoublyLinkedList();
+$a->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO | SplDoublyLinkedList::IT_MODE_DELETE);
+$a->push(1);
+$a->rewind();
+$a->unshift(2);
+var_dump($a->pop());
+var_dump($a->next());
+
+$a = new SplDoublyLinkedList();
+$a->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO | SplDoublyLinkedList::IT_MODE_DELETE);
+$a->unshift(1);
+$a->rewind();
+$a->push(2);
+var_dump($a->shift());
+var_dump($a->next());
+
+?>
+--EXPECT--
+int(1)
+NULL
+int(1)
+NULL