Unsound sending of non-Send types
dtolnay opened this issue · comments
Continued from rustsec/advisory-db#1846.
Repro of data race causing segfault in safe code:
use std::cell::Cell;
use std::thread;
use threadalone::ThreadAlone;
struct Corrupt<'a>(&'a Cell<String>);
impl<'a> Drop for Corrupt<'a> {
fn drop(&mut self) {
self.0.set(".".repeat(40));
}
}
fn main() {
let cell = Cell::new(String::new());
thread::scope(|s| loop {
let bad = ThreadAlone::new(Corrupt(&cell));
s.spawn(|| drop(bad));
cell.set(String::new());
});
}
$ cargo build && target/debug/testing >&2 2>/dev/full
Segmentation fault (core dumped)
This is the Drop impl in question:
Lines 161 to 166 in 457fd19
The intended behavior of this Drop impl was:
- If correct thread, then drop T
- If incorrect thread, then print and abort
whereas the actual behavior implemented in the above code is:
- If correct thread, then drop T
- If incorrect thread and stderr is writeable, then print and abort
- If incorrect thread and stderr is not writeable, then drop T and unwind
See https://doc.rust-lang.org/1.75.0/std/macro.eprintln.html where it calls out that eprintln can panic.
A non-panicking eprintln would look like _ = writeln!(io::stderr(), ...)
.
Oh wow, nice catch. Will publish a fix later today. If you prefer, you can commit and submit a PR then I'll merge it. (Or I'll do on my own and leave a credit)
Actually I didn't consider that eprintln can even fail 😂 In macOS there's no /dev/full so didn't understand your intent at first glance
Hey @cr0sh, is a fixed version coming soon?
I see you have yanked affected versions already, would you be OK with me merging rustsec/advisory-db#1846 before a fix is published?