From 669cbcd25aec664c465907347601e48ab51c9aed Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 17 Feb 2023 12:40:04 +0100 Subject: [PATCH] util/IntrusiveList: allow the last disposer to destroy the IntrusiveList Fixes a use-after-free bug in Co::MultiAwaitable::SetReady() when the last callback frees the Co::MultiAwaitable owner. --- src/util/IntrusiveList.hxx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/util/IntrusiveList.hxx b/src/util/IntrusiveList.hxx index 23715d11f..f222ec318 100644 --- a/src/util/IntrusiveList.hxx +++ b/src/util/IntrusiveList.hxx @@ -283,8 +283,18 @@ public: } void clear_and_dispose(Disposer auto disposer) noexcept { - while (!empty()) { - disposer(&pop_front()); + bool is_empty = empty(); + + while (!is_empty) { + auto *item = &pop_front(); + + /* by checking empty() before invoking the + disposer, it is possible for the disposer + to destroy this IntrusiveList in the last + call */ + is_empty = empty(); + + disposer(item); } }