Skip to content

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

Closed
@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