-
Notifications
You must be signed in to change notification settings - Fork 0
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
Don’t rely on Vec
’s addresses being stable
#2
Comments
Thank you very much for letting me know. 👍 I was under the impression that
of the Guarantees section with the previous description of the memory layout makes it seem as if references are guaranteed to be stable when pushing onto a Anyway, thanks again, I will address this issue as soon as |
I don't think my PR raises any instability issues (we test for that https://github.com/rust-lang/rust/blob/master/library/alloc/tests/vec.rs#L1753-L1840), but I think the main point in question is the aliasing of said pointers.
I think the current intention is to make |
@conradludgate Thanks for your comment. Is it correct then that rust-lang/rust#94421 will not cause any problems for this crate, i.e., the example provided in rust-lang/rust#94421 (comment) is in fact not UB with just the PR rust-lang/rust#94421 but it would become UB |
If the PR was merged as-is, it would mean that LLVM would have the potential to miscompile this crate, because this crate would result in LLVM UB. Rust now has to decide whether to make your crate UB — if not, the PR (and rustc) must somehow be changed to avoid miscompilations.
There is a very subtle distinction there: let mut v = Vec::with_capacity(2);
v.push(0);
let address: *const i32 = &v[0];
v.push(0);
if !ptr::eq(address, &v[0]) {
unsafe { unreachable_unchecked() };
} But this might become UB: let mut v = Vec::with_capacity(2);
v.push(0);
let mut address: *const i32 = &v[0];
v.push(0);
assert!(ptr::eq(address, &v[0]));
// Uncomment the below line to remove all the UB:
// address = &v[0];
dbg!(unsafe { &*address }); |
@SabrinaJewson Thanks for the clarification. I see that those two examples are different, however, according to the link to the test case provided by @conradludgate they seem to test for the latter case: https://github.com/rust-lang/rust/blob/master/library/alloc/tests/vec.rs#L1768-L1780 let mut v = Vec::with_capacity(128);
v.push(13);
// Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
let v0 = &mut v[0];
let v0 = unsafe { &mut *(v0 as *mut _) };
// Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
// Pushing/inserting and popping/removing
v.push(1);
v.push(2);
v.insert(1, 1);
assert_eq!(*v0, 13); It seems to me that these lines of the the test case explicitly test that the reference |
There isn’t actually, I didn’t know of that test case before. A test case doesn’t constitute a public API guarantee, but I suppose it indicates some level of commitment at a lower level of the Tower of Weakenings. Personally I would still like to see a strongly unaliased |
I see. I do not say that there is a guarantee but I am not sure that there is no guarantee either. I would like to wait until the remaining questions regarding aliasing guarantees of I would prefer using some kind of a |
I did add a test for checking for stable references and a CI job for running Miri. |
Currently this crate relies on references given out by
Vec
being stable, i.e. not invalidated by a&mut Vec<T>
. However, this is not guaranteed to be the case and will in fact change if this rust-lang/rust PR is merged. Instead, this crate should useAliasableVec
or its own pointer type so that it won’t be broken by this.The text was updated successfully, but these errors were encountered: