Description
This playground is an example of invoking UB using only the pub, safe API of this crate (pair()
, AsyncStream::new()
, and Sender::send()
): https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8cf61ab15c81d7a946cdbf60a1fd4c46
The gist of this is inside of the "generator" passed to AsyncStream::new(receiver, generator)
, we can construct a Sender
, Receiver
pair for a different type from the Receiver the AsyncStream is yielding results from. We can use this Sender to send
a u8 while generating an AsyncStream, which results in the AsyncStream yielding a String value that causes a segmentation fault when printed.
#[tokio::main(flavor = "current_thread")]
async fn main() {
let (mut sndstr, mut rcvstr) = pair::<String>();
let stream = AsyncStream::new(rcvstr, async {
let (mut sndint, mut rcvint) = pair::<u8>();
let send_fut = sndint.send(5);
// hack to get tokio to wake again after Send::send
tokio::select! {
_ = send_fut => {}
_ = async {
for _ in 1..=10 {
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
}
} => {}
}
});
for _ in 1..=10 {
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
}
stream.for_each(|item| {
println!("about to segfault:");
println!("item: {item:?}");
futures::future::ready(())
}).await;
println!("done");
}
I'm not familiar enough with the crate implementation to say which part should be marked unsafe
, but I think this shows at least one of (AsyncStream::new
, Sender::send
, pair
) needs to be marked unsafe
.