Skip to content

Commit

Permalink
Rollup merge of #82292 - SkiFire13:fix-issue-82291, r=m-ou-se
Browse files Browse the repository at this point in the history
Prevent specialized ZipImpl from calling `__iterator_get_unchecked` twice with the same index

Fixes #82291

It's open for review, but conflicts with #82289, wait before merging. The conflict involves only the new test, so it should be rather trivial to fix.
  • Loading branch information
JohnTitor committed Mar 7, 2021
2 parents 0adc196 + c1bfb9a commit 1d5b2dc
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
13 changes: 9 additions & 4 deletions library/core/src/iter/adapters/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen};
pub struct Zip<A, B> {
a: A,
b: B,
// index and len are only used by the specialized version of zip
// index, len and a_len are only used by the specialized version of zip
index: usize,
len: usize,
a_len: usize,
}
impl<A: Iterator, B: Iterator> Zip<A, B> {
pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
Expand Down Expand Up @@ -110,6 +111,7 @@ where
b,
index: 0, // unused
len: 0, // unused
a_len: 0, // unused
}
}

Expand Down Expand Up @@ -184,8 +186,9 @@ where
B: TrustedRandomAccess + Iterator,
{
fn new(a: A, b: B) -> Self {
let len = cmp::min(a.size(), b.size());
Zip { a, b, index: 0, len }
let a_len = a.size();
let len = cmp::min(a_len, b.size());
Zip { a, b, index: 0, len, a_len }
}

#[inline]
Expand All @@ -197,7 +200,7 @@ where
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
} else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a.size() {
} else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
let i = self.index;
self.index += 1;
self.len += 1;
Expand Down Expand Up @@ -262,6 +265,7 @@ where
for _ in 0..sz_a - self.len {
self.a.next_back();
}
self.a_len = self.len;
}
let sz_b = self.b.size();
if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
Expand All @@ -273,6 +277,7 @@ where
}
if self.index < self.len {
self.len -= 1;
self.a_len -= 1;
let i = self.len;
// SAFETY: `i` is smaller than the previous value of `self.len`,
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
Expand Down
23 changes: 23 additions & 0 deletions library/core/tests/iter/adapters/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,26 @@ fn test_issue_82282() {
panic!();
}
}

#[test]
fn test_issue_82291() {
use std::cell::Cell;

let mut v1 = [()];
let v2 = [()];

let called = Cell::new(0);

let mut zip = v1
.iter_mut()
.map(|r| {
called.set(called.get() + 1);
r
})
.zip(&v2);

zip.next_back();
assert_eq!(called.get(), 1);
zip.next();
assert_eq!(called.get(), 1);
}

0 comments on commit 1d5b2dc

Please sign in to comment.