summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-23 14:19:20 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-01-23 14:20:26 +0100
commitdb9776c53c50d923a26657fa150dfb2a482a6507 (patch)
tree44455013597de89a533fb302522a9a4938bb65c4
parentdd3c664f8f72263ec690f20c1eeca4c52f473dba (diff)
downloadphp-git-db9776c53c50d923a26657fa150dfb2a482a6507.tar.gz
Fixed bug #79151
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.
-rw-r--r--NEWS4
-rw-r--r--ext/spl/spl_dllist.c2
-rw-r--r--ext/spl/tests/bug79151.phpt27
3 files changed, 33 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index bbb3c919d1..20efc78daa 100644
--- 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
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 10e104270c..ba9488abfc 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -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
index 0000000000..ec4fac8324
--- /dev/null
+++ b/ext/spl/tests/bug79151.phpt
@@ -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