1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use name_it::name_it;
use futures::prelude::*;
use std::{cell::Cell, rc::Rc, sync::atomic, thread};
type X = Result<&'static [u8], &'static [()]>;
#[name_it(Foo)]
async fn foo(x: Rc<Cell<X>>) -> Rc<Cell<X>> {
x
}
fn main() {
let cell = Rc::new(Cell::new(Ok(&[][..])));
let fut = foo(cell.clone());
// Foo implements Send, even though it contains an Rc<Cell<...>>
thread::spawn(|| {
// get the Rc<Cell<...>> back out of the future
let cell = fut.now_or_never().unwrap();
// create a data race
loop {
atomic::fence(atomic::Ordering::SeqCst); // make this exploit work with --release, too
cell.set(Ok(&[][..])); // zero-element `u8` array
atomic::fence(atomic::Ordering::SeqCst); // make this exploit work with --release, too
cell.set(Err(&[(); 1000000][..])); // very long `()` array
}
});
// create a data race
loop {
atomic::fence(atomic::Ordering::SeqCst); // make this exploit work with --release, too
// check for `u8` slice with len of the `()` slice (and pointer to either one)
if let Ok(slice @ [_, ..]) = cell.get() {
for i in (0..1000000).step_by(10000) {
dbg!(slice[i]); // create a seg-fault
}
return;
}
}
}