Skip to content

Commit

Permalink
fix alloc_bytes (always allocate at least 1B)
Browse files Browse the repository at this point in the history
  • Loading branch information
Strophox committed May 23, 2024
1 parent 6ea763b commit 56c363b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 23 deletions.
37 changes: 15 additions & 22 deletions src/tools/miri/src/alloc_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ pub struct MiriAllocBytes {
/// Stored layout information about the allocation.
layout: alloc::Layout,
/// Pointer to the allocation contents.
/// Invariant:
/// * If `self.layout.size() == 0`, then `self.ptr` is some suitably aligned pointer
/// without provenance (and no actual memory was allocated).
/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
/// Invariant: `self.ptr` points to memory allocated with `self.layout`.
ptr: *mut u8,
}

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

impl Drop for MiriAllocBytes {
fn drop(&mut self) {
if self.layout.size() != 0 {
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
unsafe { alloc::dealloc(self.ptr, self.layout) }
}
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
unsafe { alloc::dealloc(self.ptr, self.layout) }
}
}

Expand All @@ -58,25 +53,23 @@ impl std::ops::DerefMut for MiriAllocBytes {
impl MiriAllocBytes {
/// This method factors out how a `MiriAllocBytes` object is allocated,
/// specifically given an allocation function `alloc_fn`.
/// `alloc_fn` is only used if `size != 0`.
/// Returns `Err(layout)` if the allocation function returns a `ptr` that is `ptr.is_null()`.
/// `alloc_fn` is only used with `size != 0`.
/// Returns `Err(layout)` if the allocation function returns a `ptr` where `ptr.is_null()`.
fn alloc_with(
size: usize,
align: usize,
alloc_fn: impl FnOnce(Layout) -> *mut u8,
) -> Result<MiriAllocBytes, Layout> {
// When size is 0 we allocate 1 byte anyway, so addresses don't possibly overlap.
let size = if size == 0 { 1 } else { size };
let layout = Layout::from_size_align(size, align).unwrap();
let ptr = if size == 0 {
std::ptr::without_provenance_mut(align)
let ptr = alloc_fn(layout);
if ptr.is_null() {
Err(layout)
} else {
let ptr = alloc_fn(layout);
if ptr.is_null() {
return Err(layout);
}
ptr
};
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
Ok(Self { ptr, layout })
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
Ok(Self { ptr, layout })
}
}
}

Expand All @@ -85,7 +78,7 @@ impl AllocBytes for MiriAllocBytes {
let slice = slice.into();
let size = slice.len();
let align = align.bytes_usize();
// SAFETY: `alloc_fn` will only be used if `size != 0`.
// SAFETY: `alloc_fn` will only be used with `size != 0`.
let alloc_fn = |layout| unsafe { alloc::alloc(layout) };
let alloc_bytes = MiriAllocBytes::alloc_with(size, align, alloc_fn)
.unwrap_or_else(|layout| alloc::handle_alloc_error(layout));
Expand All @@ -98,7 +91,7 @@ impl AllocBytes for MiriAllocBytes {
fn zeroed(size: Size, align: Align) -> Option<Self> {
let size = size.bytes_usize();
let align = align.bytes_usize();
// SAFETY: `alloc_fn` will only be used if `size != 0`.
// SAFETY: `alloc_fn` will only be used with `size != 0`.
let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };
MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()
}
Expand Down
1 change: 0 additions & 1 deletion src/tools/miri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#![feature(lint_reasons)]
#![feature(trait_upcasting)]
#![feature(strict_overflow_ops)]
#![feature(strict_provenance)]
// Configure clippy and other lints
#![allow(
clippy::collapsible_else_if,
Expand Down

0 comments on commit 56c363b

Please sign in to comment.