-
Couldn't load subscription status.
- Fork 60
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.