-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix invalid slice access in String::retain #82554
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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.