From 2a2e0e81285e46dcbd9e08699553fe49a409d16d Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Fri, 9 Jan 2026 17:14:11 +0100 Subject: [PATCH] Fix GH-20856: heap-use-after-free in SplDoublyLinkedList iterator when modifying during iteration The element may be still in use in other places, so the linking pointers should be kept consistent. If not consistent, the "move forward" code in the sample test will read a stale, dangling pointer. Closes GH-20885. --- NEWS | 4 ++++ ext/spl/spl_dllist.c | 7 +++++-- ext/spl/tests/gh20856.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 ext/spl/tests/gh20856.phpt diff --git a/NEWS b/NEWS index ab7bea69fb6..21f69b8895c 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ PHP NEWS . Fixed bug GH-18139 (Memory leak when overriding some settings via readline_info()). (ndossche) +- SPL: + . Fixed bug GH-20856 (heap-use-after-free in SplDoublyLinkedList iterator + when modifying during iteration). (ndossche) + - Standard: . Fixed bug #74357 (lchown fails to change ownership of symlink with ZTS) (Jakub Zelenka) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 5a78db2921a..2ac7980a86c 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -764,11 +764,10 @@ PHP_METHOD(SplDoublyLinkedList, offsetUnset) element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO); if (element != NULL) { - /* connect the neightbors */ + /* disconnect the neighbours */ if (element->prev) { element->prev->next = element->next; } - if (element->next) { element->next->prev = element->prev; } @@ -782,6 +781,10 @@ PHP_METHOD(SplDoublyLinkedList, offsetUnset) llist->tail = element->prev; } + /* Keep consistency if element is kept alive. */ + element->prev = NULL; + element->next = NULL; + /* finally, delete the element */ llist->count--; diff --git a/ext/spl/tests/gh20856.phpt b/ext/spl/tests/gh20856.phpt new file mode 100644 index 00000000000..8bc1b3c9582 --- /dev/null +++ b/ext/spl/tests/gh20856.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-20856 (heap-use-after-free in SplDoublyLinkedList iterator when modifying during iteration) +--CREDITS-- +vi3tL0u1s +iluuu1994 +--FILE-- + +--EXPECTF-- +object(SplStack)#%d (%d) { + ["flags":"SplDoublyLinkedList":private]=> + int(6) + ["dllist":"SplDoublyLinkedList":private]=> + array(0) { + } +}