-
Notifications
You must be signed in to change notification settings - Fork 382
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
Fix invalid aliasing and uninint memory in streams #592
Conversation
What you are saying makes sense, and thank you for detailed write up. The issue is that I cannot reproduce it (probably I don't completely understand it). I've set up CI job which runs |
Using remove_lifetime_mut to construct then hold on to both a Vec and a mutable slice into it violates the existing Rust aliasing rules, because both &mut and Unique<T> (which is used to implement Vec) assert unique access to their contents. This problem is flagged by Miri running cargo miri test. Though at the moment Stacked Borrows is experimental, the aforementioned properties are already relied upon by rustc. Getting access to the uninitialized region of a Vec as a &mut[T] is not permitted by passing invalid indexes to get_unchecked_mut, or by any other mechanism because slice::from_raw_parts documents that it requires properly initialized values of T. Though any bit pattern is a valid u8, and we never do a read, it is still invalid to construct the slice.
675da0e
to
28426bd
Compare
I clicked approve CI, github seems to not run it by default now for first-time contributors. Also, AFAIU, if can trigger the same actions in your repository. |
28426bd
to
13ef41a
Compare
Oh! Doing stuff on my own repo sounds good. I'm on my way to bed but if this latest push doesn't get thing rolling I'm sure I'll be in for a learning experience tomorrow. One test which can demonstrate the above is If you're interested in running miri generally, you can use |
|
does not select the test you mentioned, but:
does. Is bug specific to |
13ef41a
to
f739004
Compare
Okay, I think I've sorted things out now. I was wrong to point out that test case. All tests that use As I mentioned in my original comment (then forgot, apparently) to detect these issues you need So the invocation is
which I've amended the CI config to do. Without this PR, using that command you should see a failure in the test |
See the explanations and discussion in #592.
OK, trying to unfold it. First, I took The issue with this PR is that And So I tried to implement it preserving Can you please review #597? |
See the explanations and discussion in #592.
See the explanations and discussion in #592.
See the explanations and discussion in #592.
Based on PR #592 Thanks to Ben Kimock for reproducing the issue.
OK, now I patched In your PR you zero filled the vec, which is not necessary: Test pass now (except disable slow tests and tokio-bytes tests). Keeping the issue open because this code need to be ported to stable branch. Thank you for the the bugreport, prototype, review and knowledge! |
Version 2.27.0 contains the fixes. |
See the explanations and discussion in stepancheg#592.
Based on PR stepancheg#592 Thanks to Ben Kimock for reproducing the issue.
In its current state, running
cargo miri test
on this codebase flags a number of problems. This PR fixes all of those. It unfortunately does not makeMIRIFLAGS="-Zmiri-tag-raw-pointers" cargo miri test
pass completely, becausebytes
has a soundness problem which I've also put up a PR to address, and is in another aspect unanalyzable (currently?) for miri.Using
remove_lifetime_mut
to construct then hold on to both aVec
and a mutable slice into it violates the existing Rust aliasing rules in this particular usage pattern, because both&mut
andUnique<T>
(which is used to implementVec
) assert unique access to their contents. Though at the moment Stacked Borrows is experimental, the aforementioned properties are already relied upon by rustc, because it emits the LLVMnoalias
attribute for these types.The only sound way to get write access beyond the end of a
Vec
is to offset a pointer from theVec
, and access the data either through a raw pointer or as a reference toMaybeUninit<T>
because slices require that their contents must be properly initialized. Additionally, this access cannot be done throughget_unchecked_mut
because that method comes from theDeref
impl onVec
, so it is a precondition violation to use that method to access betweenlen
andcapacity
.I've tried to be somewhat surgical in what I'm changing here. Sometimes unsound constructs are used because they look simpler, so please do let me know if I should adapt the code to accomodate the valid implementation technique(s).