From 66a260617a88ed1ad55a46f03c5a90d5ad3004d3 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Fri, 19 Feb 2021 12:15:37 +0100 Subject: [PATCH 1/3] Increment self.len in specialized ZipImpl to avoid underflow in size_hint --- library/core/src/iter/adapters/zip.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 9d0f4e3618fc5..ce48016afcd50 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -200,6 +200,7 @@ where } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a.size() { let i = self.index; self.index += 1; + self.len += 1; // match the base implementation's potential side effects // SAFETY: we just checked that `i` < `self.a.len()` unsafe { From 8b9ac4d4155c74db5b317046033ab9c05a09e351 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Fri, 19 Feb 2021 12:16:12 +0100 Subject: [PATCH 2/3] Add test for underflow in specialized Zip's size_hint --- library/core/tests/iter/adapters/zip.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs index 1fce0951e365e..a597710392952 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/core/tests/iter/adapters/zip.rs @@ -245,3 +245,23 @@ fn test_double_ended_zip() { assert_eq!(it.next_back(), Some((3, 3))); assert_eq!(it.next(), None); } + +#[test] +fn test_issue_82282() { + fn overflowed_zip(arr: &[i32]) -> impl Iterator { + static UNIT_EMPTY_ARR: [(); 0] = []; + + let mapped = arr.into_iter().map(|i| *i); + let mut zipped = mapped.zip(UNIT_EMPTY_ARR.iter()); + zipped.next(); + zipped + } + + let arr = [1, 2, 3]; + let zip = overflowed_zip(&arr).zip(overflowed_zip(&arr)); + + assert_eq!(zip.size_hint(), (0, Some(0))); + for _ in zip { + panic!(); + } +} From aeb4ea739efb70e0002a4a9c4c7b8027dd0620b3 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Fri, 19 Feb 2021 12:17:48 +0100 Subject: [PATCH 3/3] Remove useless comparison since now self.index <= self.len is an invariant --- library/core/src/iter/adapters/zip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index ce48016afcd50..817fc2a51e981 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -259,7 +259,7 @@ where if sz_a != sz_b { let sz_a = self.a.size(); if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { - for _ in 0..sz_a - cmp::max(self.len, self.index) { + for _ in 0..sz_a - self.len { self.a.next_back(); } }