-
Notifications
You must be signed in to change notification settings - Fork 113
Closed
Description
It looks like the version of Focus for RRB-tree backed vectors, TreeFocus lacks bounds for Sync and Send:
Lines 280 to 285 in 22f6907
| #[allow(unsafe_code)] | |
| #[cfg(threadsafe)] | |
| unsafe impl<A> Send for TreeFocus<A> {} | |
| #[allow(unsafe_code)] | |
| #[cfg(threadsafe)] | |
| unsafe impl<A> Sync for TreeFocus<A> {} |
I realize TreeFocus is an implementation detail and not really meant to be used by end-users of the library but I think this opens up the possibility of causing data-races through safe Rust code like this:
#![forbid(unsafe_code)]
use im::vector;
use im::vector::{Vector, Focus};
use std::{iter, iter::FromIterator, cell::Cell};
use crossbeam_utils::thread;
#[derive(Debug, Clone, Copy)]
enum RefOrInt<'a> {
Ref(&'a u64),
Int(u64),
}
static SOME_INT: u64 = 123;
fn main() {
let cell = Cell::new(RefOrInt::Ref(&SOME_INT));
// Make the Vector big enough so that it gets promoted to a RRB tree.
let mut vec: Vector<&Cell<RefOrInt>> = Vector::from_iter(
iter::repeat(&cell).take(1024*5));
let focus = vec.focus();
if let Focus::Full(tree_focus) = focus {
thread::scope(|s| {
s.spawn(move |_| {
let mut sent_focus = tree_focus;
let smuggled_cell = sent_focus.get(0).unwrap();
loop {
// Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
smuggled_cell.set(RefOrInt::Ref(&SOME_INT));
smuggled_cell.set(RefOrInt::Int(0xdeadbeef));
}
});
loop {
if let RefOrInt::Ref(addr) = cell.get() {
// Hope that between the time we pattern match the object as a
// `Ref`, it gets written to by the other thread.
if addr as *const u64 == &SOME_INT as *const u64 {
continue;
}
// Due to the data race, obtaining Ref(0xdeadbeef) is possible
println!("Pointer is now: {:p}", addr);
println!("Dereferencing addr will now segfault: {}", *addr);
}
}
});
}
}which outputs
Pointer is now: 0xdeadbeef
Return Code: -11 (SIGSEGV)
(Issue found by the Rust group at @sslab-gatech)
Metadata
Metadata
Assignees
Labels
No labels