summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Meringdal <fredrikmeringdal@Fredriks-MacBook-Pro.local>2021-02-15 16:12:04 +0100
committerFredrik Meringdal <fredrikmeringdal@Fredriks-MacBook-Pro.local>2021-02-15 16:12:04 +0100
commit8cc0d3ac0f8e7030ff40958ffe63f76087c0c00e (patch)
tree8b4a58da1ec87fb581908656baaf0c8c8bb7750c
parent5a7a41849a9bdd2e92addeb74c178ef713adeb2d (diff)
downloadrust_rrule-8cc0d3ac0f8e7030ff40958ffe63f76087c0c00e.zip
infinite loop bug fix
-rw-r--r--src/rrule_iter.rs28
-rw-r--r--src/rrulestr.rs14
-rw-r--r--tests/rrule.rs3
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);
}