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.)
This commit is contained in:
Augustin Cavalier
2025-06-30 15:02:05 -04:00
parent e362f604f4
commit 7415ce0639
+12 -8
View File
@@ -173,23 +173,27 @@ void
HashedObjectCache::_ResizeHashTableIfNeeded(uint32 flags) HashedObjectCache::_ResizeHashTableIfNeeded(uint32 flags)
{ {
size_t hashSize = hash_table.ResizeNeeded(); size_t hashSize = hash_table.ResizeNeeded();
if (hashSize != 0) { if (hashSize == 0)
return;
Unlock(); Unlock();
void* buffer = slab_internal_alloc(hashSize, flags); void* buffer = slab_internal_alloc(hashSize, flags);
Lock(); Lock();
if (buffer != NULL) { if (buffer == NULL)
return;
if (hash_table.ResizeNeeded() == hashSize) { if (hash_table.ResizeNeeded() == hashSize) {
void* oldHash; void* oldHash = NULL;
hash_table.Resize(buffer, hashSize, true, &oldHash); hash_table.Resize(buffer, hashSize, true, &oldHash);
if (oldHash != NULL) { buffer = oldHash;
}
if (buffer != NULL) {
Unlock(); Unlock();
slab_internal_free(oldHash, flags); slab_internal_free(buffer, flags);
Lock(); Lock();
} }
}
}
}
} }