diff options
author | Fredrik Meringdal <fredrikmeringdal@Fredriks-MacBook-Pro.local> | 2021-02-15 16:12:04 +0100 |
---|---|---|
committer | Fredrik Meringdal <fredrikmeringdal@Fredriks-MacBook-Pro.local> | 2021-02-15 16:12:04 +0100 |
commit | 8cc0d3ac0f8e7030ff40958ffe63f76087c0c00e (patch) | |
tree | 8b4a58da1ec87fb581908656baaf0c8c8bb7750c | |
parent | 5a7a41849a9bdd2e92addeb74c178ef713adeb2d (diff) | |
download | rust_rrule-8cc0d3ac0f8e7030ff40958ffe63f76087c0c00e.zip |
infinite loop bug fix
-rw-r--r-- | src/rrule_iter.rs | 28 | ||||
-rw-r--r-- | src/rrulestr.rs | 14 | ||||
-rw-r--r-- | tests/rrule.rs | 3 |
3 files changed, 31 insertions, 14 deletions
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<Tz>; fn next(&mut self) -> Option<Self::Item> { - 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::<RRule>() + .unwrap(); + let instances: Vec<_> = rrule + .into_iter() + .skip_while(|d| *d < Local::now()) + .take(2) + .collect(); + assert_eq!(instances.len(), 0); + } } diff --git a/tests/rrule.rs b/tests/rrule.rs index e6d3376..9308360 100644 --- a/tests/rrule.rs +++ b/tests/rrule.rs @@ -25,13 +25,14 @@ mod test { let rrule = RRule::new(options); let res = rrule.all(); + println!("Acutal: {:?}", res); + println!("Expected: {:?}", expected_dates); assert_eq!( res.len(), expected_dates.len(), "Expected number of returned dates to be equal to the expected" ); - println!("Acutal: {:?}", res); for (actual, exptected) in res.iter().zip(expected_dates) { assert_eq!(actual, exptected); } |