From 385bf3ef8ed0cd3c19e7df973395b16086d1f9b7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 28 May 2021 01:53:11 +0900 Subject: [PATCH] epoch: Fix UB in Pointable impl of [MaybeUninit] --- crossbeam-epoch/src/atomic.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/crossbeam-epoch/src/atomic.rs b/crossbeam-epoch/src/atomic.rs index 75a4714ef..2484402f5 100644 --- a/crossbeam-epoch/src/atomic.rs +++ b/crossbeam-epoch/src/atomic.rs @@ -238,7 +238,8 @@ impl Pointable for T { // [`alloc::alloc::Layout::extend`] instead. #[repr(C)] struct Array { - size: usize, + /// The number of elements (not the number of bytes). + len: usize, elements: [MaybeUninit; 0], } @@ -247,31 +248,31 @@ impl Pointable for [MaybeUninit] { type Init = usize; - unsafe fn init(size: Self::Init) -> usize { - let size = mem::size_of::>() + mem::size_of::>() * size; + unsafe fn init(len: Self::Init) -> usize { + let size = mem::size_of::>() + mem::size_of::>() * len; let align = mem::align_of::>(); let layout = alloc::Layout::from_size_align(size, align).unwrap(); let ptr = alloc::alloc(layout) as *mut Array; 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); - 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); - 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); - let size = mem::size_of::>() + mem::size_of::>() * array.size; + let size = mem::size_of::>() + mem::size_of::>() * array.len; let align = mem::align_of::>(); let layout = alloc::Layout::from_size_align(size, align).unwrap(); alloc::dealloc(ptr as *mut u8, layout); @@ -1529,7 +1530,8 @@ impl 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() { @@ -1547,4 +1549,11 @@ mod tests { use super::Atomic; const _: Atomic = Atomic::::null(); } + + #[test] + fn array_init() { + let owned = Owned::<[MaybeUninit]>::init(10); + let arr: &[MaybeUninit] = &*owned; + assert_eq!(arr.len(), 10); + } }