Fix soundness issues in new

danielhenrymantilla pointed out the issues.
pull/259/head
Daniel Franklin 4 years ago
parent 8739b01e18
commit c3ba1789e7

@ -89,19 +89,31 @@ use std::ptr::NonNull;
struct Carton<T>(NonNull<T>);
impl<T> Carton<T> {
pub fn new(mut value: T) -> Self {
// Allocate enough memory on the heap to store one T
let ptr = unsafe { libc::calloc(1, size_of::<T>()) as *mut T };
pub fn new(value: T) -> Self {
// Allocate enough memory on the heap to store one T.
let memptr = &mut null_mut() as *mut *mut T;
unsafe {
let ret = libc::posix_memalign(
memptr as *mut *mut c_void,
align_of::<T>(),
size_of::<T>()
);
assert_eq!(ret, 0, "Failed to allocate or invalid alignment");
};
// NonNull is just a wrapper that enforces that the pointer isn't null.
// Malloc returns null if it can't allocate.
let mut ptr = NonNull::new(ptr).expect("We assume malloc doesn't fail");
// Move value from the stack to the location we allocated on the heap
let mut ptr = unsafe {
// Safety: memptr is dereferenceable because we created it from a
// reference and have exclusive access.
NonNull::new(*memptr)
.expect("Guaranteed non-null if posix_memalign returns 0")
};
// Move value from the stack to the location we allocated on the heap.
unsafe {
// Safety: The pointer returned by calloc is alligned, initialized,
// and dereferenceable, and we have exclusive access to the pointer.
*ptr.as_mut() = value;
// Safety: If non-null, posix_memalign gives us a ptr that is valid
// for writes and properly aligned.
ptr.as_ptr().write(value);
}
Self(ptr)

Loading…
Cancel
Save