@@ -14,8 +14,7 @@ pub struct MiriAllocBytes {
1414layout :  alloc:: Layout , 
1515    /// Pointer to the allocation contents. 
1616/// Invariant: 
17- /// * If `self.layout.size() == 0`, then `self.ptr` is some suitably aligned pointer 
18- ///   without provenance (and no actual memory was allocated). 
17+ /// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1. 
1918/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`. 
2019ptr :  * mut  u8 , 
2120} 
@@ -30,10 +29,15 @@ impl Clone for MiriAllocBytes {
3029
3130impl  Drop  for  MiriAllocBytes  { 
3231    fn  drop ( & mut  self )  { 
33-         if  self . layout . size ( )  != 0  { 
34-             // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`. 
35-             unsafe  {  alloc:: dealloc ( self . ptr ,  self . layout )  } 
36-         } 
32+         // We have to reconstruct the actual layout used for allocation. 
33+         // (`Deref` relies on `size` so we can't just always set it to at least 1.) 
34+         let  alloc_layout = if  self . layout . size ( )  == 0  { 
35+             Layout :: from_size_align ( 1 ,  self . layout . align ( ) ) . unwrap ( ) 
36+         }  else  { 
37+             self . layout 
38+         } ; 
39+         // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`. 
40+         unsafe  {  alloc:: dealloc ( self . ptr ,  alloc_layout)  } 
3741    } 
3842} 
3943
@@ -56,27 +60,25 @@ impl std::ops::DerefMut for MiriAllocBytes {
5660} 
5761
5862impl  MiriAllocBytes  { 
59-     /// This method factors out how a `MiriAllocBytes` object is allocated, 
60- /// specifically given an allocation function `alloc_fn`. 
61- /// `alloc_fn` is only used if `size != 0`. 
62- /// Returns `Err(layout)` if the allocation function returns a `ptr` that is `ptr.is_null()`. 
63+     /// This method factors out how a `MiriAllocBytes` object is allocated, given a specific allocation function. 
64+ /// If `size == 0` we allocate using a different `alloc_layout` with `size = 1`, to ensure each allocation has a unique address. 
65+ /// Returns `Err(alloc_layout)` if the allocation function returns a `ptr` where `ptr.is_null()`. 
6366fn  alloc_with ( 
6467        size :  usize , 
6568        align :  usize , 
6669        alloc_fn :  impl  FnOnce ( Layout )  -> * mut  u8 , 
6770    )  -> Result < MiriAllocBytes ,  Layout >  { 
6871        let  layout = Layout :: from_size_align ( size,  align) . unwrap ( ) ; 
69-         let  ptr = if  size == 0  { 
70-             std:: ptr:: without_provenance_mut ( align) 
72+         // When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address. 
73+         let  alloc_layout =
74+             if  size == 0  {  Layout :: from_size_align ( 1 ,  align) . unwrap ( )  }  else  {  layout } ; 
75+         let  ptr = alloc_fn ( alloc_layout) ; 
76+         if  ptr. is_null ( )  { 
77+             Err ( alloc_layout) 
7178        }  else  { 
72-             let  ptr = alloc_fn ( layout) ; 
73-             if  ptr. is_null ( )  { 
74-                 return  Err ( layout) ; 
75-             } 
76-             ptr
77-         } ; 
78-         // SAFETY: All `MiriAllocBytes` invariants are fulfilled. 
79-         Ok ( Self  {  ptr,  layout } ) 
79+             // SAFETY: All `MiriAllocBytes` invariants are fulfilled. 
80+             Ok ( Self  {  ptr,  layout } ) 
81+         } 
8082    } 
8183} 
8284
@@ -85,7 +87,7 @@ impl AllocBytes for MiriAllocBytes {
8587        let  slice = slice. into ( ) ; 
8688        let  size = slice. len ( ) ; 
8789        let  align = align. bytes_usize ( ) ; 
88-         // SAFETY: `alloc_fn` will only be used if  `size != 0`. 
90+         // SAFETY: `alloc_fn` will only be used with  `size != 0`. 
8991        let  alloc_fn = |layout| unsafe  {  alloc:: alloc ( layout)  } ; 
9092        let  alloc_bytes = MiriAllocBytes :: alloc_with ( size,  align,  alloc_fn) 
9193            . unwrap_or_else ( |layout| alloc:: handle_alloc_error ( layout) ) ; 
@@ -98,7 +100,7 @@ impl AllocBytes for MiriAllocBytes {
98100    fn  zeroed ( size :  Size ,  align :  Align )  -> Option < Self >  { 
99101        let  size = size. bytes_usize ( ) ; 
100102        let  align = align. bytes_usize ( ) ; 
101-         // SAFETY: `alloc_fn` will only be used if  `size != 0`. 
103+         // SAFETY: `alloc_fn` will only be used with  `size != 0`. 
102104        let  alloc_fn = |layout| unsafe  {  alloc:: alloc_zeroed ( layout)  } ; 
103105        MiriAllocBytes :: alloc_with ( size,  align,  alloc_fn) . ok ( ) 
104106    } 
0 commit comments