mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-03 18:43:38 +00:00
Rollup merge of #86452 - the8472:fix-zip-drop-safety, r=m-ou-se
fix panic-safety in specialized Zip::next_back This was unsound since a panic in a.next_back() would result in the length not being updated which would then lead to the same element being revisited in the side-effect preserving code. fixes #86443
This commit is contained in:
commit
504c378159
@ -295,9 +295,10 @@ where
|
||||
let sz_a = self.a.size();
|
||||
if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
|
||||
for _ in 0..sz_a - self.len {
|
||||
self.a_len -= 1;
|
||||
self.a.next_back();
|
||||
}
|
||||
self.a_len = self.len;
|
||||
debug_assert_eq!(self.a_len, self.len);
|
||||
}
|
||||
let sz_b = self.b.size();
|
||||
if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
|
||||
|
@ -232,6 +232,33 @@ fn test_zip_trusted_random_access_composition() {
|
||||
assert_eq!(z2.next().unwrap(), ((1, 1), 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(panic = "unwind")]
|
||||
fn test_zip_trusted_random_access_next_back_drop() {
|
||||
use std::panic::catch_unwind;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
|
||||
let mut counter = 0;
|
||||
|
||||
let it = [42].iter().map(|e| {
|
||||
let c = counter;
|
||||
counter += 1;
|
||||
if c == 0 {
|
||||
panic!("bomb");
|
||||
}
|
||||
|
||||
e
|
||||
});
|
||||
let it2 = [(); 0].iter();
|
||||
let mut zip = it.zip(it2);
|
||||
catch_unwind(AssertUnwindSafe(|| {
|
||||
zip.next_back();
|
||||
}))
|
||||
.unwrap_err();
|
||||
assert!(zip.next().is_none());
|
||||
assert_eq!(counter, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_ended_zip() {
|
||||
let xs = [1, 2, 3, 4, 5, 6];
|
||||
|
Loading…
Reference in New Issue
Block a user