Skip to content

Commit beec0a5

Browse files
authored
Rollup merge of rust-lang#65174 - SimonSapin:zero-box, r=alexcrichton
Fix zero-size uninitialized boxes Requesting a zero-size allocation is not allowed, return a dangling pointer instead. CC rust-lang#63291 (comment)
2 parents 14f0ed6 + 227db40 commit beec0a5

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

src/liballoc/boxed.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ impl<T> Box<T> {
142142
#[unstable(feature = "new_uninit", issue = "63291")]
143143
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
144144
let layout = alloc::Layout::new::<mem::MaybeUninit<T>>();
145+
if layout.size() == 0 {
146+
return Box(NonNull::dangling().into())
147+
}
145148
let ptr = unsafe {
146149
Global.alloc(layout)
147150
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
@@ -182,9 +185,16 @@ impl<T> Box<[T]> {
182185
#[unstable(feature = "new_uninit", issue = "63291")]
183186
pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
184187
let layout = alloc::Layout::array::<mem::MaybeUninit<T>>(len).unwrap();
185-
let ptr = unsafe { alloc::alloc(layout) };
186-
let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout));
187-
let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) };
188+
let ptr = if layout.size() == 0 {
189+
NonNull::dangling()
190+
} else {
191+
unsafe {
192+
Global.alloc(layout)
193+
.unwrap_or_else(|_| alloc::handle_alloc_error(layout))
194+
.cast()
195+
}
196+
};
197+
let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) };
188198
Box(Unique::from(slice))
189199
}
190200
}

src/liballoc/tests/boxed.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use std::ptr::NonNull;
2+
use std::mem::MaybeUninit;
3+
4+
#[test]
5+
fn unitialized_zero_size_box() {
6+
assert_eq!(
7+
&*Box::<()>::new_uninit() as *const _,
8+
NonNull::<MaybeUninit<()>>::dangling().as_ptr(),
9+
);
10+
assert_eq!(
11+
Box::<[()]>::new_uninit_slice(4).as_ptr(),
12+
NonNull::<MaybeUninit<()>>::dangling().as_ptr(),
13+
);
14+
assert_eq!(
15+
Box::<[String]>::new_uninit_slice(0).as_ptr(),
16+
NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
17+
);
18+
}

src/liballoc/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![feature(box_syntax)]
33
#![feature(drain_filter)]
44
#![feature(exact_size_is_empty)]
5+
#![feature(new_uninit)]
56
#![feature(option_flattening)]
67
#![feature(pattern)]
78
#![feature(trusted_len)]
@@ -14,6 +15,7 @@ use std::collections::hash_map::DefaultHasher;
1415

1516
mod arc;
1617
mod binary_heap;
18+
mod boxed;
1719
mod btree;
1820
mod cow_str;
1921
mod fmt;

0 commit comments

Comments
 (0)