Skip to content

Commit 02a041a

Browse files
committed
Fix sizeclass 0
1 parent 7919bd7 commit 02a041a

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/snmalloc/mem/sizeclasstable.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,21 @@ namespace snmalloc
389389
// so collapse the calculated offset.
390390
meta.div_mult = 0;
391391
}
392+
393+
// Raw sizeclass value 0 is the sentinel for uninitialized pagemap
394+
// entries (non-snmalloc memory like stack, globals, etc.).
395+
// Set size=0 so alloc_size(nullptr) returns 0, and
396+
// slab_mask=SIZE_MAX so remaining_bytes returns a large value,
397+
// preventing false-positive bounds check failures on non-heap
398+
// addresses.
399+
{
400+
auto& sentinel = fast_[0];
401+
sentinel.size = 0;
402+
size_t zero = 0;
403+
sentinel.slab_mask = ~zero;
404+
sentinel.mod_zero_mult = 1;
405+
sentinel.div_mult = 0;
406+
}
392407
}
393408
};
394409

src/test/func/large_nonpow2/large_nonpow2.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,30 @@ void test_mixed_sizes()
204204
}
205205
}
206206

207+
void test_stack_remaining_bytes()
208+
{
209+
printf(" test_stack_remaining_bytes\n");
210+
// Verify that remaining_bytes returns a large value for non-heap
211+
// addresses (stack, globals). The sizeclass sentinel (raw value 0)
212+
// must have slab_mask = SIZE_MAX so that bounds checks pass for
213+
// non-snmalloc memory. Without the sentinel fix, remaining_bytes
214+
// would return 0, causing false-positive bounds check failures.
215+
char stack_buf[64];
216+
auto remaining = snmalloc::remaining_bytes<snmalloc::Config>(
217+
snmalloc::address_cast(stack_buf));
218+
EXPECT(
219+
remaining > sizeof(stack_buf),
220+
"remaining_bytes on stack address returned {}, expected large value",
221+
remaining);
222+
223+
// Also check that alloc_size returns 0 for stack addresses.
224+
auto sc = snmalloc::Config::Backend::template get_metaentry<true>(
225+
snmalloc::address_cast(stack_buf))
226+
.get_sizeclass();
227+
auto sz = snmalloc::sizeclass_full_to_size(sc);
228+
EXPECT(sz == 0, "alloc_size on stack address returned {}, expected 0", sz);
229+
}
230+
207231
int main()
208232
{
209233
printf("large_nonpow2: non-power-of-2 large allocation tests\n");
@@ -213,6 +237,7 @@ int main()
213237
test_many_allocations();
214238
test_alloc_free_cycles();
215239
test_mixed_sizes();
240+
test_stack_remaining_bytes();
216241

217242
printf("large_nonpow2: all tests passed\n");
218243
return 0;

0 commit comments

Comments
 (0)