-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 slice access in String::retain #82554
Fix invalid slice access in String::retain #82554
Conversation
r? @m-ou-se (rust-highfive has picked a reviewer for you, use r? to override) |
cc @RalfJung |
Yeah, that seems potentially problematic. Until we have a better idea of what the aliasing model will be long-term, it's better to be conservative and always remain in-bounds even for dynamically sized references. I haven't carefully checked the code here, but a set-len-on-drop guard is a common approach elsewhere in the stdlib. Is this function covered by a liballoc test case? If yes, any idea why Miri is not complaining about this? If it is possible to cause a Miri error with the current implementation of that function, it'd be good to add that as a testcase. |
The function was covered by this test, but it contains a rust/library/alloc/tests/string.rs Lines 368 to 400 in 8e863eb
However even when run without the fn main() {
unsafe {
let mut v = vec![1, 2, 3];
v.set_len(0);
assert_eq!(*v.get_unchecked(1), 2);
let a = [1, 2, 3];
let s = &a[0..0];
assert_eq!(s.len(), 0);
assert_eq!(*s.get_unchecked(1), 2);
}
} I guess miri doesn't correctly track slices bounds but only the allocation ones? |
Miri has supported unwinding for more than a year at this point. ;)
Interesting... I first thought this was just a missing fn main() {
unsafe {
let a = [1, 2, 3];
let s = &a[0..1];
assert_eq!(s.len(), 1);
assert_eq!(*s.get_unchecked(1), 2);
}
} Something strange is going on with zero-sized references here. |
Oops, I copypasted the test without importing the |
fix reborrowing of tagged ZST references `@SkiFire13` [pointed out](rust-lang/rust#82554 (comment)) that Miri fails to detect illegal use of empty slices. This PR fixes that. In so doing, it uncovers a flaw of Stacked Borrows: it is incompatible with how the formatting machinery uses `extern type`, so for now we skip reborrowing when we cannot determine the exact size of the pointee.
This is fixed now in latest Miri, but you need to pass |
I'm a bit worried that the resulting code here is worse with a drop guard. Did you check? It might be better to keep the Alternatively, you could keep use |
I do already have most of an impl of the I think the safety comments are correct, although the actual reasons that I think |
The difference looks pretty minimal, it adds just a couple of methods and some instructions outside the main loop. https://godbolt.org/z/4rqM9P |
I forgot to update the labels Also, I correct my previous statement, it doesn't add code to the function, it just moves the return label. |
@bors r+ |
📌 Commit c89e643 has been approved by |
…ness, r=m-ou-se Fix invalid slice access in String::retain As noted in rust-lang#78499, the previous fix was technically still unsound because it accessed elements of a slice outside its bounds (even though they were still inside the same allocation). This PR addresses that concern by switching to a dropguard approach.
Rollup of 9 pull requests Successful merges: - rust-lang#80193 (stabilize `feature(osstring_ascii)`) - rust-lang#80771 (Make NonNull::as_ref (and friends) return refs with unbound lifetimes) - rust-lang#81607 (Implement TrustedLen and TrustedRandomAccess for Range<integer>, array::IntoIter, VecDequeue's iterators) - rust-lang#82554 (Fix invalid slice access in String::retain) - rust-lang#82686 (Move `std::sys::unix::platform` to `std::sys::unix::ext`) - rust-lang#82771 (slice: Stabilize IterMut::as_slice.) - rust-lang#83329 (Cleanup LLVM debuginfo module docs) - rust-lang#83336 (Fix ICE with `use clippy::a::b;`) - rust-lang#83350 (Download a more recent LLVM version if `src/version` is modified) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
As noted in #78499, the previous fix was technically still unsound because it accessed elements of a slice outside its bounds (even though they were still inside the same allocation). This PR addresses that concern by switching to a dropguard approach.