From 2371914a05f8f2763dffe6e2511d0870bcd6b461 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato 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 --- 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 817fc2a51e981..ea7a809c6badb 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -13,9 +13,10 @@ use crate::iter::{InPlaceIterable, SourceIter, TrustedLen}; pub struct Zip { 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 Zip { pub(in crate::iter) fn new(a: A, b: B) -> Zip { @@ -110,6 +111,7 @@ where b, index: 0, // unused len: 0, // unused + a_len: 0, // unused } } @@ -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] @@ -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; @@ -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 { @@ -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()` From c1bfb9a78db6d481be1d03355672712c766e20b0 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Fri, 19 Feb 2021 15:25:09 +0100 Subject: [PATCH 2/2] Add relevant test --- 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 a597710392952..000c15f72c886 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -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); +}