Skip to content

Coroutines can be assumed to be 'static despite the resume arg not being such. #132104

Closed
@danielhenrymantilla

Description

@danielhenrymantilla

I tried this code:

#![forbid(unsafe_code)]
#![feature(coroutine_trait, coroutines)]

use ::core::ops::Coroutine;
use ::std::{thread, time};

fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
    let mut generator = Box::pin({
        #[coroutine]
        move |_ctx| {
            let ctx: &'not_static str = yield;
            yield;
            dbg!(ctx);
        }
    });
    // PROBLEM: `typeof(generator) : 'static`!
    let _assert_usable_for_static: &dyn ::core::any::Any = &generator;

    // exploit:
    generator.as_mut().resume("");
    generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
    thread::spawn(move || {
        thread::sleep(time::Duration::from_millis(200));
        generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`.
    })
}

fn main() {
    let local = String::from("...");
    let thread = demo(&local);
    drop(local);
    let _unrelated = String::from("UAF");
    thread.join().unwrap();
}

I expected to see this happen:

Compilation error because 'not_static : 'static would be needed for that spawn() (or Any) to pass.

Instead, this happened:

No compilation error, thus unsoundness ensues (coroutine prints UAF in the current playground, thereby proving it is reading unrelated/UAF memory. Miri reports UB).

Meta

  • rustc --version --verbose:

    2024-10-23 4f2f477fded0a47b21ed
    

@rustbot label +I-unsound +A-coroutines +F-coroutines +F-coroutine_trait +requires-nightly

Metadata

Metadata

Labels

A-coroutinesArea: CoroutinesC-bugCategory: This is a bug.F-coroutines`#![feature(coroutines)]`I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundnessrequires-nightlyThis issue requires a nightly compiler in some way.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions