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 {

27302831

impl Drop for MiriAllocBytes {

2932

fn 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

}

52605361

impl 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(

5966

size: usize,

6067

align: usize,

6168

alloc_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 };

6570

let 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);

6775

if ptr.is_null() {

68-

Err(layout)

76+

Err(alloc_layout)

6977

} else {

7078

// SAFETY: All `MiriAllocBytes` invariants are fulfilled.

7179

Ok(Self { ptr, layout })