From 23d3ff1b9756c768c4412dcd1d80cff0617fd5c5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 6 Oct 2019 23:45:25 +0200 Subject: [PATCH 1/3] Fix zero-size uninitialized boxes Requesting a zero-size allocation is not allowed, return a dangling pointer instead. CC https://github.com/rust-lang/rust/issues/63291#issuecomment-538692745 --- src/liballoc/boxed.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9b5d9431ae204..2693a64e13ba1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,6 +141,9 @@ impl Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { + if mem::size_of::() == 0 { + return Box(NonNull::dangling().into()) + } let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) @@ -181,10 +184,17 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let layout = alloc::Layout::array::>(len).unwrap(); - let ptr = unsafe { alloc::alloc(layout) }; - let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); - let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + let ptr = if mem::size_of::() == 0 || len == 0 { + NonNull::dangling() + } else { + let layout = alloc::Layout::array::>(len).unwrap(); + unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + .cast() + } + }; + let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) }; Box(Unique::from(slice)) } } From ca1cfdab78d1966efd492cd550a3684f3b95527c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:32:58 +0200 Subject: [PATCH 2/3] Uninitialized boxes: check for zero-size allocation based on Layout::size --- src/liballoc/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2693a64e13ba1..567b8ea722491 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,10 +141,10 @@ impl Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { - if mem::size_of::() == 0 { + let layout = alloc::Layout::new::>(); + if layout.size() == 0 { return Box(NonNull::dangling().into()) } - let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) @@ -184,10 +184,10 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let ptr = if mem::size_of::() == 0 || len == 0 { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = if layout.size() == 0 { NonNull::dangling() } else { - let layout = alloc::Layout::array::>(len).unwrap(); unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) From 227db40a98e5bd903aa3658c16f19a3d6f694deb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:33:55 +0200 Subject: [PATCH 3/3] Uninitialized boxes: add test for zero-size allocations --- src/liballoc/tests/boxed.rs | 18 ++++++++++++++++++ src/liballoc/tests/lib.rs | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 src/liballoc/tests/boxed.rs diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs new file mode 100644 index 0000000000000..bc3d53bf30da3 --- /dev/null +++ b/src/liballoc/tests/boxed.rs @@ -0,0 +1,18 @@ +use std::ptr::NonNull; +use std::mem::MaybeUninit; + +#[test] +fn unitialized_zero_size_box() { + assert_eq!( + &*Box::<()>::new_uninit() as *const _, + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[()]>::new_uninit_slice(4).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[String]>::new_uninit_slice(0).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); +} diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 5723a30c0f34f..59f5c8dfb8a87 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,6 +2,7 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(new_uninit)] #![feature(option_flattening)] #![feature(pattern)] #![feature(repeat_generic_slice)] @@ -15,6 +16,7 @@ use std::collections::hash_map::DefaultHasher; mod arc; mod binary_heap; +mod boxed; mod btree; mod cow_str; mod fmt;