-
Notifications
You must be signed in to change notification settings - Fork 398
Description
If I understand correctly, Miri replaces the allocator, even when the #[global_allocator]
attribute is used to specify a custom allocator. Unfortunately, this can lead to Miri thinking that a program invokes UB when it does not.
In the following example, I implement a custom allocator where alloc
reserves the first machine word in each block in order to store a header, it then returns a pointer to the next address. Since Miri replaces this with its own allocator, dereferencing a pointer to the header's offset will be out-of-bounds.
#![feature(alloc_layout_extra)]
use std::alloc::{GlobalAlloc, Layout, System};
use std::mem::size_of;
#[global_allocator]
static ALLOCATOR: Allocator = Allocator {};
const HEADER: usize = 42;
struct Allocator {}
unsafe impl GlobalAlloc for Allocator {
// Allocate a block with a usize sized header, and return a pointer to the
// next address.
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let (new_layout, _) = Layout::new::<usize>().extend(layout).unwrap();
let base_ptr = System.alloc(new_layout) as *mut usize;
::std::ptr::write(base_ptr, HEADER);
base_ptr.add(1) as *mut u8
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let (new_layout, _) = Layout::new::<usize>().extend(layout).unwrap();
let base_ptr = (ptr as *mut usize).wrapping_sub(1) as *mut u8;
System.dealloc(base_ptr, new_layout);
}
}
fn main() {
let block = Box::into_raw(Box::new(123_usize));
// Get a pointer to the block header using integer arithmetic.
let header_ptr = (block as usize - size_of::<usize>()) as *mut usize;
assert_eq!(unsafe { *header_ptr }, HEADER); // Miri error: dangling pointer dereference
// Get a pointer to the block header using wrapping_sub.
let header_ptr = block.wrapping_sub(1);
assert_eq!(unsafe { *header_ptr }, HEADER); // Miri error: overflowing in-bounds pointer arithmetic
unsafe { Box::from_raw(block) };
}
Running this under miri causes an evaluation error upon the first misuse of header_ptr
:
Compiling playground v0.0.1 (/playground)
error: Miri evaluation error: dangling pointer was dereferenced
--> src/main.rs:34:25
|
34 | assert_eq!(unsafe { *header_ptr }, HEADER); // Miri error: dangling pointer dereference
| ^^^^^^^^^^^ dangling pointer was dereferenced
|
Is this kind of support possible? Alternatively, perhaps if suppression support landed this may be an ideal use-case. [issue #788]