Skip to content

Commit f7e9a77

Browse files
committed
IterRangeFrom: overflow panic after yielding MAX
check overflow after yielding MAX value new `0_u8..` will yield `255` and only panic on the subsequent `next()`
1 parent 5b67b09 commit f7e9a77

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

core/src/range/iter.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::iter::{
33
};
44
use crate::num::NonZero;
55
use crate::range::{Range, RangeFrom, RangeInclusive, legacy};
6+
use crate::{intrinsics, mem};
67

78
/// By-value [`Range`] iterator.
89
#[unstable(feature = "new_range_api", issue = "125687")]
@@ -293,12 +294,25 @@ range_incl_exact_iter_impl! {
293294
/// By-value [`RangeFrom`] iterator.
294295
#[unstable(feature = "new_range_api", issue = "125687")]
295296
#[derive(Debug, Clone)]
296-
pub struct IterRangeFrom<A>(legacy::RangeFrom<A>);
297+
pub struct IterRangeFrom<A> {
298+
start: A,
299+
/// Whether the first element of the iterator has yielded.
300+
/// Only used when overflow checks are enabled.
301+
first: bool,
302+
}
297303

298-
impl<A> IterRangeFrom<A> {
304+
impl<A: Step> IterRangeFrom<A> {
299305
/// Returns the remainder of the range being iterated over.
306+
#[inline]
307+
#[rustc_inherit_overflow_checks]
300308
pub fn remainder(self) -> RangeFrom<A> {
301-
RangeFrom { start: self.0.start }
309+
if intrinsics::overflow_checks() {
310+
if !self.first {
311+
return RangeFrom { start: Step::forward(self.start, 1) };
312+
}
313+
}
314+
315+
RangeFrom { start: self.start }
302316
}
303317
}
304318

@@ -307,18 +321,47 @@ impl<A: Step> Iterator for IterRangeFrom<A> {
307321
type Item = A;
308322

309323
#[inline]
324+
#[rustc_inherit_overflow_checks]
310325
fn next(&mut self) -> Option<A> {
311-
self.0.next()
326+
if intrinsics::overflow_checks() {
327+
if self.first {
328+
self.first = false;
329+
return Some(self.start.clone());
330+
}
331+
332+
self.start = Step::forward(self.start.clone(), 1);
333+
return Some(self.start.clone());
334+
}
335+
336+
let n = Step::forward(self.start.clone(), 1);
337+
Some(mem::replace(&mut self.start, n))
312338
}
313339

314340
#[inline]
315341
fn size_hint(&self) -> (usize, Option<usize>) {
316-
self.0.size_hint()
342+
(usize::MAX, None)
317343
}
318344

319345
#[inline]
346+
#[rustc_inherit_overflow_checks]
320347
fn nth(&mut self, n: usize) -> Option<A> {
321-
self.0.nth(n)
348+
if intrinsics::overflow_checks() {
349+
if self.first {
350+
self.first = false;
351+
352+
let plus_n = Step::forward(self.start.clone(), n);
353+
self.start = plus_n.clone();
354+
return Some(plus_n);
355+
}
356+
357+
let plus_n = Step::forward(self.start.clone(), n);
358+
self.start = Step::forward(plus_n.clone(), 1);
359+
return Some(self.start.clone());
360+
}
361+
362+
let plus_n = Step::forward(self.start.clone(), n);
363+
self.start = Step::forward(plus_n.clone(), 1);
364+
Some(plus_n)
322365
}
323366
}
324367

@@ -334,6 +377,6 @@ impl<A: Step> IntoIterator for RangeFrom<A> {
334377
type IntoIter = IterRangeFrom<A>;
335378

336379
fn into_iter(self) -> Self::IntoIter {
337-
IterRangeFrom(self.into())
380+
IterRangeFrom { start: self.start, first: true }
338381
}
339382
}

0 commit comments

Comments
 (0)