Skip to content

Unwrapping LayoutError for overflowed Rc<[T]>/Arc<[T]> capacity #136797

Description

@thaliaarchi

When constructing a Rc<[T]> or Arc<[T]> with a capacity exceeding isize::MAX, taking into account the size used for their headers, they cause a panic by unwrapping a LayoutError. Instead, they should panic with a more helpful error like Vec<T> and Box<[T]> do. This seems to be a simple oversight.

For example:

const MAX: usize = isize::MAX as usize;
type Header = (usize, usize);
const S: usize = size_of::<Header>();
const A: usize = align_of::<Header>();
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1); // layout error
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1); // layout error
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1); // layout error
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1); // layout error
called `Result::unwrap()` on an `Err` value: LayoutError
See all LayoutError panic backtraces
thread 'main' panicked at library/alloc/src/rc.rs:298:49:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
   3: core::result::Result<T,E>::unwrap
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
   4: alloc::rc::rc_inner_layout_for_value_layout
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/rc.rs:298:5
   5: alloc::rc::Rc<T>::allocate_for_layout
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2057:22
   6: alloc::rc::Rc<[T]>::allocate_for_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2136:13
   7: alloc::rc::Rc<[T]>::new_uninit_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:1050:31
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/rc.rs:298:49:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
   3: core::result::Result<T,E>::unwrap
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
   4: alloc::rc::rc_inner_layout_for_value_layout
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/rc.rs:298:5
   5: alloc::rc::Rc<T>::allocate_for_layout
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:2057:22
   6: alloc::rc::Rc<[T]>::new_zeroed_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/rc.rs:1078:26
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/sync.rs:367:50:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
   3: core::result::Result<T,E>::unwrap
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
   4: alloc::sync::arcinner_layout_for_value_layout
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/sync.rs:367:5
   5: alloc::sync::Arc<T>::allocate_for_layout
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1950:22
   6: alloc::sync::Arc<[T]>::allocate_for_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:2037:13
   7: alloc::sync::Arc<[T]>::new_uninit_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1168:32
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S + 1);
thread 'main' panicked at library/alloc/src/sync.rs:367:50:
called `Result::unwrap()` on an `Err` value: LayoutError
stack backtrace:
   3: core::result::Result<T,E>::unwrap
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/core/src/result.rs:1109:23
   4: alloc::sync::arcinner_layout_for_value_layout
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/sync.rs:367:5
   5: alloc::sync::Arc<T>::allocate_for_layout
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1950:22
   6: alloc::sync::Arc<[T]>::new_zeroed_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/sync.rs:1197:27

In contrast, in this same case, Vec<T> and Box<[T]> panic with a more useful capacity overflow:

Vec::<u8>::with_capacity(MAX + 1); // capacity overflow
vec![0u8; MAX + 1]; // capacity overflow
Box::<[u8]>::new_uninit_slice(MAX + 1); // capacity overflow
Box::<[u8]>::new_zeroed_slice(MAX + 1); // capacity overflow
capacity overflow
See all capacity overflow backtraces
Vec::<u8>::with_capacity(MAX + 1);
thread 'main' panicked at src/main.rs:11:9:
capacity overflow
stack backtrace:
   2: alloc::raw_vec::capacity_overflow
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
   3: alloc::raw_vec::handle_error
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
   4: alloc::raw_vec::RawVecInner<A>::with_capacity_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:426:25
   5: alloc::raw_vec::RawVec<T,A>::with_capacity_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:186:20
   6: alloc::vec::Vec<T,A>::with_capacity_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:803:20
   7: alloc::vec::Vec<T>::with_capacity
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:483:9
vec![0u8; MAX + 1];
thread 'main' panicked at src/main.rs:12:9:
capacity overflow
stack backtrace:
   2: alloc::raw_vec::capacity_overflow
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
   3: alloc::raw_vec::handle_error
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
   4: alloc::raw_vec::RawVecInner<A>::with_capacity_zeroed_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:445:25
   5: alloc::raw_vec::RawVec<T,A>::with_capacity_zeroed_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:208:20
   6: <u8 as alloc::vec::spec_from_elem::SpecFromElem>::from_elem
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/spec_from_elem.rs:55:31
   7: alloc::vec::from_elem
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3189:5
Box::<[u8]>::new_uninit_slice(MAX + 1);
thread 'main' panicked at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:688:18:
capacity overflow
stack backtrace:
   2: alloc::raw_vec::capacity_overflow
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
   3: alloc::raw_vec::handle_error
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
   4: alloc::raw_vec::RawVecInner::with_capacity
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:148:25
   5: alloc::raw_vec::RawVec<T>::with_capacity
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:124:23
   6: alloc::boxed::Box<[T]>::new_uninit_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:688:18
Box::<[u8]>::new_zeroed_slice(MAX + 1);
thread 'main' panicked at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:713:18:
capacity overflow
stack backtrace:
   2: alloc::raw_vec::capacity_overflow
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:25:5
   3: alloc::raw_vec::handle_error
             at /rustc/43ca9d18e333797f0aa3b525501a7cec8d61a96b/library/alloc/src/raw_vec.rs:793:29
   4: alloc::raw_vec::RawVecInner<A>::with_capacity_zeroed_in
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:445:25
   5: alloc::raw_vec::RawVec<T>::with_capacity_zeroed
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec.rs:134:20
   6: alloc::boxed::Box<[T]>::new_zeroed_slice
             at ~/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/boxed.rs:713:18
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S + 1);

For completeness, all of these constructors consistently handle failed allocations for valid capacities with alloc::handle_alloc_error:

Vec::<u8>::with_capacity(MAX);
// memory allocation of 9223372036854775807 bytes failed
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
// memory allocation of 9223372036854775800 bytes failed
See all memory allocation failures
Vec::<u8>::with_capacity(MAX);
memory allocation of 9223372036854775807 bytes failed
vec![0u8; MAX];
memory allocation of 9223372036854775807 bytes failed
Box::<[u8]>::new_uninit_slice(MAX);
memory allocation of 9223372036854775807 bytes failed
Box::<[u8]>::new_zeroed_slice(MAX);
memory allocation of 9223372036854775807 bytes failed
Rc::<[u8]>::new_uninit_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Rc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Arc::<[u8]>::new_uninit_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
Arc::<[u8]>::new_zeroed_slice((MAX / A * A) - S);
memory allocation of 9223372036854775800 bytes failed
$ rustc --version --verbose
rustc 1.86.0-nightly (43ca9d18e 2025-02-08)
binary: rustc
commit-hash: 43ca9d18e333797f0aa3b525501a7cec8d61a96b
commit-date: 2025-02-08
host: x86_64-apple-darwin
release: 1.86.0-nightly
LLVM version: 19.1.7

(Similarly on Rust 1.84.1)

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions