Shallow box drop creates mutable reference to memory that has already been moved away
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Code like this
fn foo<T>(x: Box<T>) {
std::mem::forget(*x);
}
generates MIR like this
bb1: {
_4 = &mut _1;
_5 = <Box<T> as Drop>::drop(move _4) -> [return: bb3, unwind continue];
}
This is a call of the drop function on Box (which usually cannot be directly called), it is not a drop terminator.
The problem with this is that the box contents have already been moved out at this point. If validity is recursive through Box and &mut, that means this call is UB because the validity invariant of T may no longer hold. This currently causes tons of UB in safe code when turning on Miri's recursive validation mode:
error: Undefined Behavior: constructing invalid value at .<deref>.<deref>.<dyn-downcast>.<captured-var(x)>: encountered uninitialized memory, but expected an integer
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2240:51
|
2240 | <F as FnOnce<Args>>::call_once(*self, args)
| ^ Undefined Behavior occurred here
|
= 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: stack backtrace:
0: <std::boxed::Box<dyn std::ops::FnOnce() -> i32> as std::ops::FnOnce<()>>::call_once
at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2240:51: 2240:52
1: boxed_fn_once
at tests/pass/closures.rs:48:5: 48:8
2: main
at tests/pass/closures.rs:118:9: 121:12
Also see https://github.com/rust-lang/unsafe-code-guidelines/issues/412
Cc @rust-lang/opsem
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the example and examining its generated MIR, then run the affected case with Miri's recursive validation mode. Inspect alloc/src/boxed.rs around line 2240 and tests/pass/closures.rs around the cited locations. Done means establishing corrected handling for the shallow box drop and adding coverage that no invalid reference or UB is reported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100