-
Notifications
You must be signed in to change notification settings - Fork 348
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
Miri and provenance using raw_ref
macros
#1695
Comments
This is caused by how Stacked Borrows treats the "reference to raw transition" in let s = S { a: 42, b: 27 };
let at_b = ::core::ptr::raw_const!(s.b); Here, the raw pointer is conceptually being created to let s = S { a: 42, b: 27 };
let s_raw = &s as *const _;
let at_b = ::core::ptr::raw_const!((*s_raw).b); Now, So, as far as I can see Miri is working as intended here; Stacked Borrows just doesn't behave the way you expected it to. And that's a fair point, Stacked Borrows maybe should be more permissive here -- but that's not a Miri issue, that's a memory model issue: rust-lang/unsafe-code-guidelines#134.
Interesting; I'll look into this. At first sight I am surprised that this works with just a reference.
Given that hardly anything solid can be said about our aliasing model at this point, I am not sure what the docs could usefully say that is actually "official". |
I cannot reproduce this. I adjusted your code to make it actually run, simplified a bit, and arrived at this, which still fails: #![feature(raw_ref_macros)]
fn main() {
#[derive(Debug)]
#[repr(C)] // for easier computation of the field offsets (no need to `offset_of!`)
struct S {
a: u8,
b: u8,
}
let s = S { a: 42, b: 27 };
let raw_s = &s; // adding `as *const S` makes it work
unsafe {
let at_b = std::ptr::raw_const!((*raw_s).b);
dbg!(
&*at_b.offset(-1 /* offset of `.b` in `S` */)
);
}
} |
FWIW, I can't reproduce this either 😅 If the Playground's miri hasn't been updated since, then I guess I had a typo on my test. Disregard that part, then.
To clarify, I get the SB memory model w.r.t., aliasing, or at least the issue you linked to. I am not trying to refute it; on the contrary, I am trying to act based on them, for the sake of conservativeness (assume UB until the requirement is loosened, if ever). That's what I meant by provenance: I am wondering about the "SB-related rights" the obtained pointers have. In order to think / study about that, precisely because there is no documentation on the topic, I've had to resort to using Miri. Given that miri has had instances of both false positives and false negatives, the fact that
Given your answer, I now understand that it is the former: the (What follows does not really belong to the miri repo, but rather the Rust one: if we do open a new issue I'll cut-&-paste that there)
I know this is not an easy topic, since in Rust many "formal semantics" have not been decided / fixed yet, but precisely because of that, I think we1 should try to assume the stricter models available, while waiting for the semantics to be loosened, if ever. In this instance, until the SB aliasing model is "officially blessed" or partly "officially rejected" / changed, it is best if code that we1 write right now treats the SB memory model as "already officially blessed", so as to avoid it getting rejected in the future because of there being too many instance of "incorrect code". So, in the same fashion that Or in more practical terms: the fact that Miri itself rejects code violating parts of the SB memory model does mean that we1 should be given a way to know why.
Thus, I do think that the docs could benefit from rules expressing the most conservative hypothesis about UB rules. For instance, the |
I think this is not really actionable on the Miri side. We now enable raw pointer tagging by default, so the rules are hopefully less confusing. |
The following code:
triggers the following Miri error:
Which means that
ptr::raw_const!(s.b)
is interpreted as having provenance overs.b
only; i.e., that it is not equivalent to doingptr::raw_const!(s).cast::<u8>().offset( offset_of!(S, b) )
More surprisingly, ifat_b
is computed as:then Miri does not complain.This looks like a bug (Miri false positive), although I can imagine that having the
raw_ref!
macros "guess" the right provenance might be hard to implement, if not impossible; but these differences in semantics with changes that subtle look error-prone and footgunny to me; at the very least the docs of theraw_ref
macros ought to mention that extra care should be taken when dealing with provenance (that is, to recommend using the explicitat_s.cast::<u8>.offset(offset_of!(S, field)).cast::<FieldTy>()
, withoffset_of!
being the one that usesraw_ref!
macros under the hood).This might be an important thing to clarify / to fix now that the macros are about to be stabilized (rust-lang/rust#80886)
The text was updated successfully, but these errors were encountered: