Skip to content

core::iter::repeat_n is unsound with Box<T> #130141

@jwong101

Description

@jwong101

This is technically different from #130140 as there's no UAF. However, using core::iter::repeat_n with Box<T> has undefined behavior if you use the last/original element after moving the iterator, since the Box field has noalias properties.

fn main() { let mut y = std::iter::repeat_n(Box::new(0), 1); let x = y.next().unwrap(); let _z = y; dbg!(*x); }
Miri Backtrace

Compiling playground v0.0.1 (/playground) Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.96s Running `/playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/playground` error: Undefined Behavior: attempting a read access using <2719> at alloc1241[0x0], but that tag does not exist in the borrow stack for this location --> src/main.rs:5:5 | 5 | dbg!(*x); | ^^^^^^^^ | | | attempting a read access using <2719> at alloc1241[0x0], but that tag does not exist in the borrow stack for this location | this error occurs as part of an access at alloc1241[0x0..0x4] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: <2719> was created by a Unique retag at offsets [0x0..0x4] --> src/main.rs:3:13 | 3 | let x = y.next().unwrap(); | ^^^^^^^^^^^^^^^^^ help: <2719> was later invalidated at offsets [0x0..0x4] by a Unique retag (of a reference/box inside this compound value) --> src/main.rs:4:14 | 4 | let _z = y; | ^ = note: BACKTRACE (of the first span): = note: inside `main` at /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/macros.rs:364:13: 364:16 = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error 

Wrapping the element using MaybeUninit (or MaybeDangling once we have that) should make this sound.

Metadata

Metadata

Assignees

Labels

A-boxArea: Our favorite opsem complicationC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-criticalCritical priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.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