Skip to content

Commit

Permalink
epoch: Fix UB in Pointable impl of [MaybeUninit<T>]
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed May 27, 2021
1 parent c093db3 commit 385bf3e
Showing 1 changed file with 17 additions and 8 deletions.
25 changes: 17 additions & 8 deletions crossbeam-epoch/src/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ impl<T> Pointable for T {
// [`alloc::alloc::Layout::extend`] instead.
#[repr(C)]
struct Array<T> {
size: usize,
/// The number of elements (not the number of bytes).
len: usize,
elements: [MaybeUninit<T>; 0],
}

Expand All @@ -247,31 +248,31 @@ impl<T> Pointable for [MaybeUninit<T>] {

type Init = usize;

unsafe fn init(size: Self::Init) -> usize {
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * size;
unsafe fn init(len: Self::Init) -> usize {
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * len;
let align = mem::align_of::<Array<T>>();
let layout = alloc::Layout::from_size_align(size, align).unwrap();
let ptr = alloc::alloc(layout) as *mut Array<T>;
if ptr.is_null() {
alloc::handle_alloc_error(layout);
}
(*ptr).size = size;
(*ptr).len = len;
ptr as usize
}

unsafe fn deref<'a>(ptr: usize) -> &'a Self {
let array = &*(ptr as *const Array<T>);
slice::from_raw_parts(array.elements.as_ptr() as *const _, array.size)
slice::from_raw_parts(array.elements.as_ptr() as *const _, array.len)
}

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut Self {
let array = &*(ptr as *mut Array<T>);
slice::from_raw_parts_mut(array.elements.as_ptr() as *mut _, array.size)
slice::from_raw_parts_mut(array.elements.as_ptr() as *mut _, array.len)
}

unsafe fn drop(ptr: usize) {
let array = &*(ptr as *mut Array<T>);
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * array.size;
let size = mem::size_of::<Array<T>>() + mem::size_of::<MaybeUninit<T>>() * array.len;
let align = mem::align_of::<Array<T>>();
let layout = alloc::Layout::from_size_align(size, align).unwrap();
alloc::dealloc(ptr as *mut u8, layout);
Expand Down Expand Up @@ -1529,7 +1530,8 @@ impl<T: ?Sized + Pointable> Default for Shared<'_, T> {

#[cfg(all(test, not(crossbeam_loom)))]
mod tests {
use super::Shared;
use super::{Owned, Shared};
use std::mem::MaybeUninit;

#[test]
fn valid_tag_i8() {
Expand All @@ -1547,4 +1549,11 @@ mod tests {
use super::Atomic;
const _: Atomic<u8> = Atomic::<u8>::null();
}

#[test]
fn array_init() {
let owned = Owned::<[MaybeUninit<usize>]>::init(10);
let arr: &[MaybeUninit<usize>] = &*owned;
assert_eq!(arr.len(), 10);
}
}

0 comments on commit 385bf3e

Please sign in to comment.