fix alloc_bytes (always allocate at least 1B) · rust-lang/rust@56c363b (original) (raw)

`@@ -13,10 +13,7 @@ pub struct MiriAllocBytes {

`

13

13

`/// Stored layout information about the allocation.

`

14

14

`layout: alloc::Layout,

`

15

15

`/// Pointer to the allocation contents.

`

16

``

`-

/// Invariant:

`

17

``

`` -

/// * If self.layout.size() == 0, then self.ptr is some suitably aligned pointer

``

18

``

`-

/// without provenance (and no actual memory was allocated).

`

19

``

`` -

/// * Otherwise, self.ptr points to memory allocated with self.layout.

``

``

16

`` +

/// Invariant: self.ptr points to memory allocated with self.layout.

``

20

17

`ptr: *mut u8,

`

21

18

`}

`

22

19

``

`@@ -30,10 +27,8 @@ impl Clone for MiriAllocBytes {

`

30

27

``

31

28

`impl Drop for MiriAllocBytes {

`

32

29

`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

``

`-

}

`

``

30

`` +

// SAFETY: Invariant, self.ptr points to memory allocated with self.layout.

``

``

31

`+

unsafe { alloc::dealloc(self.ptr, self.layout) }

`

37

32

`}

`

38

33

`}

`

39

34

``

`@@ -58,25 +53,23 @@ impl std::ops::DerefMut for MiriAllocBytes {

`

58

53

`impl MiriAllocBytes {

`

59

54

`` /// This method factors out how a MiriAllocBytes object is allocated,

``

60

55

`` /// 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().

``

``

56

`` +

/// alloc_fn is only used with size != 0.

``

``

57

`` +

/// Returns Err(layout) if the allocation function returns a ptr where ptr.is_null().

``

63

58

`fn alloc_with(

`

64

59

`size: usize,

`

65

60

`align: usize,

`

66

61

`alloc_fn: impl FnOnce(Layout) -> *mut u8,

`

67

62

`) -> 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 };

`

68

65

`let layout = Layout::from_size_align(size, align).unwrap();

`

69

``

`-

let ptr = if size == 0 {

`

70

``

`-

std::ptr::without_provenance_mut(align)

`

``

66

`+

let ptr = alloc_fn(layout);

`

``

67

`+

if ptr.is_null() {

`

``

68

`+

Err(layout)

`

71

69

`} 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 })

`

``

70

`` +

// SAFETY: All MiriAllocBytes invariants are fulfilled.

``

``

71

`+

Ok(Self { ptr, layout })

`

``

72

`+

}

`

80

73

`}

`

81

74

`}

`

82

75

``

`@@ -85,7 +78,7 @@ impl AllocBytes for MiriAllocBytes {

`

85

78

`let slice = slice.into();

`

86

79

`let size = slice.len();

`

87

80

`let align = align.bytes_usize();

`

88

``

`` -

// SAFETY: alloc_fn will only be used if size != 0.

``

``

81

`` +

// SAFETY: alloc_fn will only be used with size != 0.

``

89

82

`let alloc_fn = |layout| unsafe { alloc::alloc(layout) };

`

90

83

`let alloc_bytes = MiriAllocBytes::alloc_with(size, align, alloc_fn)

`

91

84

`.unwrap_or_else(|layout| alloc::handle_alloc_error(layout));

`

`@@ -98,7 +91,7 @@ impl AllocBytes for MiriAllocBytes {

`

98

91

`fn zeroed(size: Size, align: Align) -> Option {

`

99

92

`let size = size.bytes_usize();

`

100

93

`let align = align.bytes_usize();

`

101

``

`` -

// SAFETY: alloc_fn will only be used if size != 0.

``

``

94

`` +

// SAFETY: alloc_fn will only be used with size != 0.

``

102

95

`let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };

`

103

96

`MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()

`

104

97

`}

`