[alloc] Add CheckedSlabBStackAllocator for secure slab allocation#7
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a new experimental allocator, CheckedSlabBStackAllocator, intended to provide crash-recoverable fixed-block slab allocation with runtime double-free detection on top of BStack storage.
Changes:
- Added
CheckedSlabBStackAllocatorimplementation with per-block overhead metadata and accompanying unit tests. - Exported the new allocator through
allocand the crate root whenalloc + setfeatures are enabled. - Extended existing allocator fuzz test suite coverage to include the new checked slab allocator.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/lib.rs |
Documents and re-exports CheckedSlabBStackAllocator under alloc + set. |
src/alloc/mod.rs |
Adds the new checked_slab module and re-exports the allocator type. |
src/alloc/checked_slab.rs |
Implements the new crash-recoverable checked slab allocator and unit tests. |
src/alloc_fuzz_tests.rs |
Adds fuzz-suite instantiations for the checked slab allocator. |
PLANNED.md |
Updates planned design notes wording around overhead-bit validation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Original PLANNED entry: Adding
|
| Value | Meaning |
|---|---|
0x0000_0000_0000_0000 |
Block is free. data[0..8] holds the next-free offset (little-endian u64, sentinel u64::MAX). |
0x8NNN_NNNN_NNNN_NNNN |
Block is in use; NNN_NNNN_NNNN_NNNN is the allocation size in number of blocks; high bit is always 1. |
Note: due to the fact that the minimum block size is 16 bytes, the maximum allocation size in number of blocks is 2^63 / 16 = 2^59 blocks, which means the 2nd-5th hex digits of the overhead are always zero. These bits may not be checked. They may be used in the future for additional metadata if needed.
block_size covers the full block including the 8-byte overhead. The slice returned to the caller covers data only, i.e. block_size − 8 bytes per slab block.
alloc(len): Compute the number of blocks needed as ceil((len + 8) / block_size). Pop the required count from the free list (verifying each overhead is zero; return an error on mismatch), write the overhead as (num_blocks | 0x8000_0000_0000_0000), zero data[0..8], and update the header. Fall back to tail extension if the free list is insufficient.
dealloc(slice): Read the overhead. If the high bit is clear (overhead is zero), the block is already free — return a double-free error without modifying the list. Otherwise do similar processing as dealloc of SlabBStackAllocator.
realloc: Same policy as SlabBStackAllocator with overhead updated on size changes.
Crash recovery: On open, scan the arena linearly. Any block whose overhead is non-zero and whose high bit is set is live; any block whose overhead is zero is free. A scan can reconstruct a valid free list from scratch if needed.
The Feature Checklist
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@williamwutq Review |
CheckedSlabBStackAllocator
Description: Fixed-block slab allocator. All blocks in the arena are exactly
block_sizebytes (≥ 16) with 8 byte overhead per block. Provides fast allocation within in the size range and general (but slower) allocation for arbitrary sized blocks. Additionally provides double free protection and other corruption protection measures.Important Feature: No
Type: Allocator
Magic Number: ALCK
Bulk: No
Tests: Needed
Feature Flags: alloc + set
Breaking change: No
New Types:
CheckedSlabBStackAllocatorRust Only: No
Fuzz: Yes
Safety Review: Needed: Crash Safety, Invariants