AK: Avoid UAF for consecutive SinglyLinkedList removals

The iterator returned by SinglyLinkedList::remove() left `m_prev`
default-initialized to `nullptr`. If the caller removed another element
without first advancing, the previous node's next pointer was left
dangling to the freed node.

This caused a UAF in FinalizationRegistry's `remove_by_token()` when
two consecutive records shared an unregister token.
This commit is contained in:
Tim Ledbetter 2026-04-21 16:11:52 +01:00 committed by Jelle Raaijmakers
parent 75ae9abe7a
commit df34c626d8
2 changed files with 24 additions and 0 deletions

View file

@ -281,6 +281,7 @@ public:
auto* next = node->next;
new_iterator.m_node = next;
new_iterator.m_next = next ? next->next : nullptr;
new_iterator.m_prev = iterator.m_prev;
delete node;
return new_iterator;
}

View file

@ -204,3 +204,26 @@ TEST_CASE(singly_linked_list_remove_does_not_leave_dangling_iterator)
EXPECT(it == list.end());
EXPECT(list.is_empty());
}
TEST_CASE(singly_linked_list_remove_consecutive_mid_list_nodes)
{
SinglyLinkedList<int> list;
list.append(1);
list.append(2);
list.append(3);
list.append(4);
auto it = list.begin();
++it;
it = list.remove(it);
EXPECT_EQ(*it, 3);
it = list.remove(it);
EXPECT_EQ(*it, 4);
it = list.begin();
EXPECT_EQ(*it, 1);
++it;
EXPECT_EQ(*it, 4);
++it;
EXPECT(it == list.end());
}