From 8cc0d3ac0f8e7030ff40958ffe63f76087c0c00e Mon Sep 17 00:00:00 2001 From: Fredrik Meringdal Date: Mon, 15 Feb 2021 16:12:04 +0100 Subject: infinite loop bug fix --- src/rrule_iter.rs | 28 +++++++++++++++------------- src/rrulestr.rs | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/rrule_iter.rs b/src/rrule_iter.rs index d88d034..64bcb5d 100644 --- a/src/rrule_iter.rs +++ b/src/rrule_iter.rs @@ -19,16 +19,16 @@ pub struct RRuleIter { } impl RRuleIter { - pub fn generate(&mut self) { + pub fn generate(&mut self) -> bool { let options = self.ii.options.clone(); match options.count { - Some(count) if count == 0 => return, + Some(count) if count == 0 => return true, _ => (), }; if self.counter_date.year() > MAX_YEAR { - return; + return true; } while self.buffer.is_empty() { @@ -73,7 +73,7 @@ impl RRuleIter { } // This means that the real count is 0, because of the decrement above if count == 1 { - return; + return true; } } } @@ -98,7 +98,7 @@ impl RRuleIter { self.timeset[k].second as u32, ); if options.until.is_some() && res > options.until.unwrap() { - return; + return true; } if res >= options.dtstart { self.buffer.push_back(res); @@ -109,7 +109,7 @@ impl RRuleIter { } // This means that the real count is 0, because of the decrement above if count == 1 { - return; + return true; } } } @@ -118,14 +118,14 @@ impl RRuleIter { } if options.interval == 0 { - return; + return true; } // Handle frequency and interval self.counter_date = increment_counter_date(self.counter_date, &options, filtered); if self.counter_date.year() > MAX_YEAR { - return; + return true; } if options.freq == Frequenzy::Hourly @@ -146,6 +146,8 @@ impl RRuleIter { self.ii.rebuild(year as isize, month as usize); } + + false } } @@ -153,15 +155,15 @@ impl Iterator for RRuleIter { type Item = DateTime; fn next(&mut self) -> Option { - if self.finished { - return None; - } - if !self.buffer.is_empty() { return self.buffer.pop_front(); } - self.generate(); + if self.finished { + return None; + } + + self.finished = self.generate(); if self.buffer.is_empty() { self.finished = true; diff --git a/src/rrulestr.rs b/src/rrulestr.rs index 62d1faa..bf616ba 100644 --- a/src/rrulestr.rs +++ b/src/rrulestr.rs @@ -748,4 +748,18 @@ mod test { assert_eq!(occurences.len(), 7); assert!(Utc::now().timestamp() - occurences[0].timestamp() < 2); } + + #[test] + fn avoids_infinite_loop() { + let rrule = + "DTSTART:20200427T090000\nFREQ=WEEKLY;UNTIL=20200506T035959Z;BYDAY=FR,MO,TH,TU,WE" + .parse::() + .unwrap(); + let instances: Vec<_> = rrule + .into_iter() + .skip_while(|d| *d < Local::now()) + .take(2) + .collect(); + assert_eq!(instances.len(), 0); + } } -- cgit v1.2.3