- Notifications
You must be signed in to change notification settings - Fork 59
Open
Labels
Description
The current docs have the following example:
// Initialize the allocator BEFORE you use it { use core::mem::MaybeUninit; const HEAP_SIZE: usize = 1024; static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } }
However, the init
function looks like this:
pub unsafe fn init(&self, start_addr: usize, size: usize) { critical_section::with(|cs| { let block: &[u8] = core::slice::from_raw_parts(start_addr as *const u8, size); self.heap .borrow(cs) .borrow_mut() .insert_free_block_ptr(block.into()); }); }
This is undefined behavior, you are creating a &[u8]
from uninit memory. This could be replaced with something like:
static mut HEAP_MEM: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
And the heap would still reside in .bss
and wouldn't be UB.
Furthermore, I think the init
code is also unsound, at least under stacked borrows, because you create an immutable slice, then hand it to Tlsf
to write to it, which does not have the provenance necessary to do so. There's probably another method you can use to create the NonNull<[u8]>
for insert_free_block_ptr
which does not create an intervening slice, which might also bypass the first unsoundness here.
In general, we should fix this quickly, and yank the current versions affected.