From db9776c53c50d923a26657fa150dfb2a482a6507 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 23 Jan 2020 14:19:20 +0100 Subject: 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. --- NEWS | 4 ++++ ext/spl/spl_dllist.c | 2 ++ ext/spl/tests/bug79151.phpt | 27 +++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 ext/spl/tests/bug79151.phpt 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-- +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 -- cgit v1.2.1