From d824b9db2b339650b4dd04ffae5ede8abd84889c Mon Sep 17 00:00:00 2001 From: Daan Date: Mon, 13 May 2024 10:11:57 -0700 Subject: [PATCH] fix page collection where a freed segment could be accessed --- src/heap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/heap.c b/src/heap.c index 2fb04f7a..6c56edd6 100644 --- a/src/heap.c +++ b/src/heap.c @@ -95,6 +95,11 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL)); mi_collect_t collect = *((mi_collect_t*)arg_collect); _mi_page_free_collect(page, collect >= MI_FORCE); + if (collect == MI_FORCE) { + // note: call before a potential `_mi_page_free` as the segment may be freed if this was the last used page in that segment. + mi_segment_t* segment = _mi_page_segment(page); + _mi_segment_collect(segment, true /* force? */, &heap->tld->segments); + } if (mi_page_all_free(page)) { // no more used blocks, free the page. // note: this will free retired pages as well. @@ -104,10 +109,6 @@ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t // still used blocks but the thread is done; abandon the page _mi_page_abandon(page, pq); } - if (collect == MI_FORCE) { - mi_segment_t* segment = _mi_page_segment(page); - _mi_segment_collect(segment, true /* force? */, &heap->tld->segments); - } return true; // don't break }