Skip to content

Commit

Permalink
Fix UB when dropping BoxBytes owning a zero-sized layout (#258)
Browse files Browse the repository at this point in the history
  • Loading branch information
zachs18 authored Jul 30, 2024
1 parent 005ee32 commit 1c75146
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,9 @@ impl<I: ?Sized, T: ?Sized + TransparentWrapper<I>> TransparentWrapperAlloc<I>

/// As `Box<[u8]>`, but remembers the original alignment.
pub struct BoxBytes {
// SAFETY: `ptr` is owned, was allocated with `layout`, and points to
// `layout.size()` initialized bytes.
// SAFETY: `ptr` is owned, points to `layout.size()` initialized bytes, and
// was allocated with `layout` (unless `layout.size() == 0` in which case it
// is dangling).
ptr: NonNull<u8>,
layout: Layout,
}
Expand All @@ -770,8 +771,11 @@ impl DerefMut for BoxBytes {

impl Drop for BoxBytes {
fn drop(&mut self) {
// SAFETY: See type invariant.
unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout) };
if self.layout.size() != 0 {
// SAFETY: See type invariant: if `self.layout.size() != 0`, then
// `self.ptr` is owned and was allocated with `self.layout`.
unsafe { alloc::alloc::dealloc(self.ptr.as_ptr(), self.layout) };
}
}
}

Expand Down
14 changes: 14 additions & 0 deletions tests/cast_slice_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,17 @@ fn test_arc_slices() {
let empty: Arc<[i8]> = cast_slice_arc::<(), i8>(Arc::new([(); 42]));
assert!(empty.is_empty());
}

#[cfg(feature = "extern_crate_alloc")]
#[test]
fn box_bytes_zst() {
let x: BoxBytes = box_bytes_of(Box::new([0u8; 0]));
let _: Box<[u8]> = from_box_bytes(x);

let x: BoxBytes = box_bytes_of(Box::new([0u8; 0]));
let res: Result<Box<[()]>, _> = try_from_box_bytes(x);
assert_eq!(res.unwrap_err().0, PodCastError::SizeMismatch);

let x: BoxBytes = box_bytes_of(Box::new([(); 0]));
let _: Box<[u8]> = from_box_bytes(x);
}

0 comments on commit 1c75146

Please sign in to comment.