Skip to content

Commit cd7c005

Browse files
committed
lsregion: fix slab_unmap() called on malloced slab
Lsregion allocates slabs using either - Slab_map() from slab arena, when allocation size is smaller, than slab size; - Using cached slab, stored in the lsregion as a protection from oscillation; - Using malloc(), when requested size is too big. Malloc() was used when allocation size was >= fixed slab size - meta size. However free() was used, when real slab size was > fixed slab size - meta size. So if an allocation was exactly of size 'fixed slab size - meta size', it was allocated using malloc(), but freed using slab_unmap(). That lead to a crash, if 'lucky'. But as it is a memory corruption, could lead to anything.
1 parent 5706060 commit cd7c005

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

small/lsregion.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ lsregion_alloc_slow(struct lsregion *lsregion, size_t size, int64_t id)
4545
}
4646
if ((slab != NULL && size > lslab_unused(slab)) ||
4747
slab == NULL) {
48-
if (size + lslab_sizeof() >= slab_size) {
48+
if (size + lslab_sizeof() > slab_size) {
4949
/* Large allocation, use malloc() */
5050
slab_size = size + lslab_sizeof();
5151
struct quota *quota = lsregion->arena->quota;

test/lsregion.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ test_basic()
140140
is(lsregion_slab_count(&allocator), 0,
141141
"slab count after large gc()");
142142

143+
/*
144+
* Allocate exactly slab size.
145+
*/
146+
++id;
147+
data = lsregion_alloc(&allocator, arena.slab_size - lslab_sizeof(), id);
148+
lsregion_gc(&allocator, id);
149+
143150
lsregion_destroy(&allocator);
144151
/* Sic: slabs are cached by arena */
145152
is(arena.used, 2 * arena.slab_size, "arena used after destroy");

0 commit comments

Comments
 (0)