From 1e1a12bf3c4194ee121776aa3d383b218442c2a2 Mon Sep 17 00:00:00 2001 From: daanx Date: Tue, 24 Dec 2024 17:07:11 -0800 Subject: [PATCH] fix rounding issue with huge size allocations --- include/mimalloc/internal.h | 5 +++-- include/mimalloc/types.h | 2 +- src/page.c | 19 ++++++++----------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 5b877635..0e161951 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h @@ -706,9 +706,10 @@ static inline bool mi_page_is_huge(const mi_page_t* page) { (mi_memkind_is_os(page->memid.memkind) && page->memid.mem.os.base < (void*)page)); } - static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) { - return &((mi_heap_t*)heap)->pages[_mi_bin(size)]; + mi_page_queue_t* const pq = &((mi_heap_t*)heap)->pages[_mi_bin(size)]; + if (size <= MI_LARGE_MAX_OBJ_SIZE) { mi_assert_internal(pq->block_size <= MI_LARGE_MAX_OBJ_SIZE); } + return pq; } diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index 627aa6f9..4bede252 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -328,7 +328,7 @@ typedef struct mi_page_s { // (Except for large pages since huge objects are allocated in 4MiB chunks) #define MI_SMALL_MAX_OBJ_SIZE ((MI_SMALL_PAGE_SIZE-MI_PAGE_INFO_SIZE)/8) // < 8 KiB #define MI_MEDIUM_MAX_OBJ_SIZE ((MI_MEDIUM_PAGE_SIZE-MI_PAGE_INFO_SIZE)/8) // < 64 KiB -#define MI_LARGE_MAX_OBJ_SIZE ((MI_LARGE_PAGE_SIZE-MI_PAGE_INFO_SIZE)/4) // < 512 KiB +#define MI_LARGE_MAX_OBJ_SIZE (MI_LARGE_PAGE_SIZE/4) // <= 512 KiB // note: this must be a nice power of 2 or we get rounding issues with _mi_bin #define MI_LARGE_MAX_OBJ_WSIZE (MI_LARGE_MAX_OBJ_SIZE/MI_SIZE_SIZE) diff --git a/src/page.c b/src/page.c index 9a96da85..542496a0 100644 --- a/src/page.c +++ b/src/page.c @@ -883,18 +883,15 @@ static mi_page_t* mi_huge_page_alloc(mi_heap_t* heap, size_t size, size_t page_a // Allocate a page // Note: in debug mode the size includes MI_PADDING_SIZE and might have overflowed. static mi_page_t* mi_find_page(mi_heap_t* heap, size_t size, size_t huge_alignment) mi_attr_noexcept { - mi_page_queue_t* pq = mi_page_queue(heap, (huge_alignment ? MI_LARGE_MAX_OBJ_SIZE+1 : size)); + const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` + if mi_unlikely(req_size > MI_MAX_ALLOC_SIZE) { + _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size); + return NULL; + } + mi_page_queue_t* pq = mi_page_queue(heap, (huge_alignment > 0 ? MI_LARGE_MAX_OBJ_SIZE+1 : size)); // huge allocation? - if mi_unlikely(mi_page_queue_is_huge(pq)) { - const size_t req_size = size - MI_PADDING_SIZE; // correct for padding_size in case of an overflow on `size` - //if mi_unlikely(req_size > (MI_LARGE_MAX_OBJ_SIZE - MI_PADDING_SIZE) || huge_alignment > 0) { - if mi_unlikely(req_size > MI_MAX_ALLOC_SIZE) { - _mi_error_message(EOVERFLOW, "allocation request is too large (%zu bytes)\n", req_size); - return NULL; - } - else { - return mi_huge_page_alloc(heap,size,huge_alignment,pq); - } + if mi_unlikely(mi_page_queue_is_huge(pq) || req_size > MI_MAX_ALLOC_SIZE) { + return mi_huge_page_alloc(heap,size,huge_alignment,pq); } else { // otherwise find a page with free blocks in our size segregated queues