From 7415ce0639052c769e2b241f15bf393c5b335bd9 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 30 Jun 2025 15:02:05 -0400 Subject: [PATCH] kernel/slab: Fix potential memory leak in HashedObjectCache. If the resize-needed amount changed while we were allocating memory, then we'd leak the new buffer. In testing, I added an ASSERT() to check if this case actually happened, and it didn't seem to fire when using the system (with a debug kernel though, admittedly.) Inspired by a change suggested on GitHub, but implemented in a completely different way (that cleans up the code at the same time.) --- src/system/kernel/slab/HashedObjectCache.cpp | 34 +++++++++++--------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/system/kernel/slab/HashedObjectCache.cpp b/src/system/kernel/slab/HashedObjectCache.cpp index bca3f361b6..4e3f464706 100644 --- a/src/system/kernel/slab/HashedObjectCache.cpp +++ b/src/system/kernel/slab/HashedObjectCache.cpp @@ -173,22 +173,26 @@ void HashedObjectCache::_ResizeHashTableIfNeeded(uint32 flags) { size_t hashSize = hash_table.ResizeNeeded(); - if (hashSize != 0) { - Unlock(); - void* buffer = slab_internal_alloc(hashSize, flags); - Lock(); + if (hashSize == 0) + return; - if (buffer != NULL) { - if (hash_table.ResizeNeeded() == hashSize) { - void* oldHash; - hash_table.Resize(buffer, hashSize, true, &oldHash); - if (oldHash != NULL) { - Unlock(); - slab_internal_free(oldHash, flags); - Lock(); - } - } - } + Unlock(); + void* buffer = slab_internal_alloc(hashSize, flags); + Lock(); + + if (buffer == NULL) + return; + + if (hash_table.ResizeNeeded() == hashSize) { + void* oldHash = NULL; + hash_table.Resize(buffer, hashSize, true, &oldHash); + buffer = oldHash; + } + + if (buffer != NULL) { + Unlock(); + slab_internal_free(buffer, flags); + Lock(); } }