Skip to content

Commit

Permalink
Rollup merge of rust-lang#65174 - SimonSapin:zero-box, r=alexcrichton
Browse files Browse the repository at this point in the history
Fix zero-size uninitialized boxes

Requesting a zero-size allocation is not allowed, return a dangling pointer instead.

CC rust-lang#63291 (comment)
  • Loading branch information
Centril authored Oct 19, 2019
2 parents 14f0ed6 + 227db40 commit 76a7e3e
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ impl<T> Box<T> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
if layout.size() == 0 {
return Box(NonNull::dangling().into())
}
let ptr = unsafe {
Global.alloc(layout)
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
Expand Down Expand Up @@ -182,9 +185,16 @@ impl<T> Box<[T]> {
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(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 layout.size() == 0 {
NonNull::dangling()
} else {
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))
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/liballoc/tests/boxed.rs
Original file line number Diff line number Diff line change
@@ -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::<MaybeUninit<()>>::dangling().as_ptr(),
);
assert_eq!(
Box::<[()]>::new_uninit_slice(4).as_ptr(),
NonNull::<MaybeUninit<()>>::dangling().as_ptr(),
);
assert_eq!(
Box::<[String]>::new_uninit_slice(0).as_ptr(),
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
);
}
2 changes: 2 additions & 0 deletions src/liballoc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![feature(box_syntax)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(new_uninit)]
#![feature(option_flattening)]
#![feature(pattern)]
#![feature(trusted_len)]
Expand All @@ -14,6 +15,7 @@ use std::collections::hash_map::DefaultHasher;

mod arc;
mod binary_heap;
mod boxed;
mod btree;
mod cow_str;
mod fmt;
Expand Down

0 comments on commit 76a7e3e

Please sign in to comment.