121 lines
3.9 KiB
Diff
121 lines
3.9 KiB
Diff
From 0babb88efc4d36f3defafc3c3c0343793fa05d52 Mon Sep 17 00:00:00 2001
|
|
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
|
|
Date: Wed, 3 Mar 2021 21:09:01 +0100
|
|
Subject: [PATCH 1/2] Prevent Zip specialization from calling
|
|
__iterator_get_unchecked twice with the same index after calling next_back
|
|
|
|
(cherry picked from commit 2371914a05f8f2763dffe6e2511d0870bcd6b461)
|
|
---
|
|
library/core/src/iter/adapters/zip.rs | 13 +++++++++----
|
|
1 file changed, 9 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
|
|
index dcbcb1ce7200..7dac0c63ca2d 100644
|
|
--- a/library/core/src/iter/adapters/zip.rs
|
|
+++ b/library/core/src/iter/adapters/zip.rs
|
|
@@ -13,9 +13,10 @@
|
|
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> {
|
|
@@ -110,6 +111,7 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|
b,
|
|
index: 0, // unused
|
|
len: 0, // unused
|
|
+ a_len: 0, // unused
|
|
}
|
|
}
|
|
|
|
@@ -184,8 +186,9 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
|
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]
|
|
@@ -197,7 +200,7 @@ fn next(&mut self) -> Option<(A::Item, B::Item)> {
|
|
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;
|
|
@@ -264,6 +267,7 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
|
for _ in 0..sz_a - self.len {
|
|
self.a.next_back();
|
|
}
|
|
+ self.a_len = self.len;
|
|
}
|
|
let sz_b = self.b.size();
|
|
if b_side_effect && sz_b > self.len {
|
|
@@ -275,6 +279,7 @@ fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
|
}
|
|
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()`
|
|
--
|
|
2.31.1
|
|
|
|
|
|
From 19af66a6f3e2bbb4780bb9eae7eb53bd13e3dd0f Mon Sep 17 00:00:00 2001
|
|
From: Giacomo Stevanato <giaco.stevanato@gmail.com>
|
|
Date: Fri, 19 Feb 2021 15:25:09 +0100
|
|
Subject: [PATCH 2/2] Add relevant test
|
|
|
|
(cherry picked from commit c1bfb9a78db6d481be1d03355672712c766e20b0)
|
|
---
|
|
library/core/tests/iter/adapters/zip.rs | 23 +++++++++++++++++++++++
|
|
1 file changed, 23 insertions(+)
|
|
|
|
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
|
|
index a59771039295..000c15f72c88 100644
|
|
--- a/library/core/tests/iter/adapters/zip.rs
|
|
+++ b/library/core/tests/iter/adapters/zip.rs
|
|
@@ -265,3 +265,26 @@ fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
|
|
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);
|
|
+}
|
|
--
|
|
2.31.1
|
|
|