-
Notifications
You must be signed in to change notification settings - Fork 475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AtomicCell
accessing uninitialized memory
#748
Comments
I don't think this is actually a problem, but it doesn't let me run miri. So I am implementing this myself. See crossbeam-rs/crossbeam#748
This seems an instance of rust-lang/unsafe-code-guidelines#69? I don't know if there is a way to fix this issue other than to restrict the types that can be used in AtomicCell using something like unsafe marker traits. |
Well, having uninitialized tags violates Rust's UB rules: enum values must have valid discriminants. It seems like the
No; working with uninit data requires |
But isn't the discriminant valid in the above example? My understanding is that the rest of the enum is uninitialized (because writing |
Yes, and a
|
I assume this is the relevant
Unfortunately all the types are inferred here so I am not sure at which type this is invoked. But it just occurred to me that this might be an instance of rust-lang/rust#69488. AtomicCell will load the entire 8-byte data at type The proper fix is to do the (atomic) load at type |
so is it not possible to implement a sound |
AtomicCell goes beyond what is soundly possible in Rust in multiple ways -- besides this issue, also see #315. Furthermore, it uses an SeqLock, which cannot be soundly implemented in C/C++/Rust (see e.g. this article). |
Minimized: #[allow(dead_code)]
#[repr(align(8))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Test {
Field(u32),
FieldLess,
}
fn main() {
unsafe {
let v = Test::FieldLess;
let v = std::mem::transmute::<_, u64>(v);
let _v = std::mem::transmute::<_, Test>(v); // error: Undefined Behavior: type validation failed at .<enum-tag>: encountered uninitialized bytes, but expected a valid enum tag
}
} And using let v = Test::FieldLess;
- let v = std::mem::transmute::<_, u64>(v);
+ let v = std::mem::transmute::<_, [u64; 1]>(v);
let _v = std::mem::transmute::<_, Test>(v); I agree that this appears to be an instance of rust-lang/rust#69488. |
Ah, that is an interesting work-around -- looks like single-element arrays get a different ABI than their element type, so they are not treated as scalars any more. That said, this more of a Miri quirk than a proper fix. |
Btw, I implemented a C++ proposal p1478r1 to fix SeqLock's problem (repository: atomic-memcpy), but I had the same problem with padding that this issue encountered. |
Btw, there is another way to trigger the same problem, which maybe shows a bit clearly what happens: use crossbeam_utils::atomic::AtomicCell;
#[derive(Copy, Clone, Debug)]
#[repr(align(4))]
struct Test(u8, u16);
fn main() {
assert!(AtomicCell::<Test>::is_lock_free());
let x = AtomicCell::new(Test(1, 2));
println!("{:?}", x.load());
}
|
Run the follow code sample with
cargo +nightly miri run
I see the following error from Miri
I think the root of this issue is that
AtomicCell
is trying to do atransmute_copy
on theNone
value, but the upper bits are uninitialized, thereforeAtomicCell
is reading uninitialized data.crossbeam-utils = "0.8.5"
cargo 1.56.0-nightly (cc17afbb0 2021-08-02)
The text was updated successfully, but these errors were encountered: