differentiate between layout and alloc_layout · rust-lang/rust@1b374df
@@ -13,7 +13,10 @@ pub struct MiriAllocBytes {
1313/// Stored layout information about the allocation.
1414 layout: alloc::Layout,
1515/// Pointer to the allocation contents.
16- /// Invariant: `self.ptr` points to memory allocated with `self.layout`.
16+ /// Invariant:
17+ /// * If `self.layout.size() == 0`, then `self.ptr` is some suitably aligned pointer
18+ /// that was allocated with the same layout but `size == 1`.
19+ /// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
1720 ptr: *mut u8,
1821}
1922@@ -27,8 +30,13 @@ impl Clone for MiriAllocBytes {
27302831impl Drop for MiriAllocBytes {
2932fn drop(&mut self) {
33+let alloc_layout = if self.layout.size() == 0 {
34+Layout::from_size_align(1, self.layout.align()).unwrap()
35+} else {
36+self.layout
37+};
3038// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
31-unsafe { alloc::dealloc(self.ptr, self.layout) }
39+unsafe { alloc::dealloc(self.ptr, alloc_layout) }
3240}
3341}
3442@@ -51,21 +59,21 @@ impl std::ops::DerefMut for MiriAllocBytes {
5159}
52605361impl MiriAllocBytes {
54-/// This method factors out how a `MiriAllocBytes` object is allocated,
55- /// specifically given an allocation function `alloc_fn`.
56- /// `alloc_fn` is only used with `size != 0`.
57- /// Returns `Err(layout)` if the allocation function returns a `ptr` where `ptr.is_null()`.
62+/// This method factors out how a `MiriAllocBytes` object is allocated, given a specific allocation function.
63+ /// If `size == 0` we allocate using a different `alloc_layout` with `size = 1`, to ensure each allocation has a unique address.
64+ /// Returns `Err(alloc_layout)` if the allocation function returns a `ptr` where `ptr.is_null()`.
5865 fn alloc_with(
5966size: usize,
6067align: usize,
6168alloc_fn: impl FnOnce(Layout) -> *mut u8,
6269) -> Result<MiriAllocBytes, Layout> {
63-// When size is 0 we allocate 1 byte anyway, so addresses don't possibly overlap.
64-let size = if size == 0 { 1 } else { size };
6570let layout = Layout::from_size_align(size, align).unwrap();
66-let ptr = alloc_fn(layout);
71+// When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
72+let alloc_layout =
73+if size == 0 { Layout::from_size_align(1, align).unwrap() } else { layout };
74+let ptr = alloc_fn(alloc_layout);
6775if ptr.is_null() {
68-Err(layout)
76+Err(alloc_layout)
6977} else {
7078// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
7179Ok(Self { ptr, layout })