Of course it features support for custom allocators and thus unstable API, but I presume the equivalent on the global allocator would be doable. Also it supports custom allocators incorrectly , as it turns out… that’s why I enjoy URLO. Makes you also find new issues while answering questions.
opened 09:12PM - 08 Jan 24 UTC
I-unsound
C-bug
requires-nightly
needs-triage
```rs
/*
[dependencies]
bumpalo = { version = "3", features = ["allocator_api… "] }
*/
#![feature(allocator_api)]
use bumpalo::Bump;
use std::rc::Rc;
fn main() {
let bump = Bump::new();
let boxx = Box::new_in(42, &bump);
let rc = Rc::<i32, _>::from(boxx);
}
```
run [on rustexplorer.com](https://www.rustexplorer.com/b#LyoKW2RlcGVuZGVuY2llc10KYnVtcGFsbyA9IHsgdmVyc2lvbiA9ICIzIiwgZmVhdHVyZXMgPSBbImFsbG9jYXRvcl9hcGkiXSB9CiovCgojIVtmZWF0dXJlKGFsbG9jYXRvcl9hcGkpXQoKdXNlIGJ1bXBhbG86OkJ1bXA7CnVzZSBzdGQ6OnJjOjpSYzsKCgpmbiBtYWluKCkgewogICAgbGV0IGJ1bXAgPSBCdW1wOjpuZXcoKTsKICAgIGxldCBib3h4ID0gQm94OjpuZXdfaW4oNDIsICZidW1wKTsKCiAgICBsZXQgcmMgPSBSYzo6PGkzMiwgXz46OmZyb20oYm94eCk7Cn0K)
Output:
~~~
free(): invalid pointer
~~~
Miri:
~~~
error: Undefined Behavior: deallocating 0x258bc[alloc1011]<2851> which does not point to the beginning of an object
--> /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:117:14
|
117 | unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ deallocating 0x258bc[alloc1011]<2851> which does not point to the beginning of an object
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::alloc::dealloc` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:117:14: 117:64
= note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/alloc.rs:254:22: 254:51
= note: inside `<std::boxed::Box<std::mem::ManuallyDrop<i32>> as std::ops::Drop>::drop` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:1244:17: 1244:66
= note: inside `std::ptr::drop_in_place::<std::boxed::Box<std::mem::ManuallyDrop<i32>>> - shim(Some(std::boxed::Box<std::mem::ManuallyDrop<i32>>))` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:507:1: 507:56
= note: inside `std::mem::drop::<std::boxed::Box<std::mem::ManuallyDrop<i32>>>` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/mod.rs:992:24: 992:25
= note: inside `std::rc::Rc::<i32, &bumpalo::Bump>::from_box_in` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/rc.rs:1928:13: 1928:22
= note: inside `<std::rc::Rc<i32, &bumpalo::Bump> as std::convert::From<std::boxed::Box<i32, &bumpalo::Bump>>>::from` at /home/frank/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/rc.rs:2504:9: 2504:27
note: inside `main`
--> src/main.rs:16:14
|
16 | let rc = Rc::<i32, _>::from(boxx);
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
~~~
The underlying issue was found when reviewing the implementation of `From<Box<T, A>> for Rc<T, A>`. The code is a reproduction to trigger the unsoundness. The implementation in question features:
https://github.com/rust-lang/rust/blob/ca663b06c5492ac2dde5e53cd11579fa8e4d68bd/library/alloc/src/rc.rs#L1912-L1932
Where `Box<T, A>` is turned into `Box<MaybeUninit<T>>` and dropped. Yes, that’s `Box<MaybeUninit<T>, Global>`, not `Box<MaybeUninit<T>, A>`.
The code for `Arc` seems to be doing the same thing.
https://github.com/rust-lang/rust/blob/ca663b06c5492ac2dde5e53cd11579fa8e4d68bd/library/alloc/src/sync.rs#L1858-L1877
The code for `From<Vec<T, A>> for Rc<[T]>` (and the same thing for `Arc`) seems to properly use a `Vec<MaybeUninit<T>, &A>`… no actually, that’s a `Vec<T, &A>` with zero lengths… notably the allocator is correct though.
https://github.com/rust-lang/rust/blob/ca663b06c5492ac2dde5e53cd11579fa8e4d68bd/library/alloc/src/rc.rs#L2521-L2535
@rustbot label I-unsound requires-nightly