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