Skip to content

Commit

Permalink
Catching another infinite loop condition.
Browse files Browse the repository at this point in the history
Fixes sabre-io#329. Thanks for the research @PHPGangsta
  • Loading branch information
evert authored and EoleDev committed Jul 25, 2018
1 parent 881c9ab commit 19f3c45
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,8 @@ ChangeLog
------------------

*
* #329: Infinite loop when using `BYMONTHDAY`, `BYDAY` and/or `BYSETPOS` to
expand a `BYMONTH` rule.

4.1.6 (2018-04-20)
------------------
Expand Down
20 changes: 17 additions & 3 deletions lib/Recur/RRuleIterator.php
Expand Up @@ -620,19 +620,33 @@ protected function nextYearly() {

}

$currentMonth = $this->currentDate->format('n');
$currentYear = $this->currentDate->format('Y');
$currentDayOfMonth = $this->currentDate->format('j');
//$currentMonth = $this->currentDate->format('n');
//$currentYear = $this->currentDate->format('Y');
//$currentDayOfMonth = $this->currentDate->format('j');

$advancedToNewMonth = false;

$noOccurrenceCounter = 0;

// If we got a byDay or getMonthDay filter, we must first expand
// further.
if ($this->byDay || $this->byMonthDay) {

while (true) {

$occurrences = $this->getMonthlyOccurrences();
if(!$occurrences) {
// We are counting subsequent months where there weren't
// occurrences. If we exceed the treshold we might be
// dealing with a recurrence rule that doesn't generate
// valid instances.
$noOccurrenceCounter++;
if (++$noOccurrenceCounter > 10) {
throw new InvalidDataException('BYDAY, BYMONTHDAY and/or BYSETPOS rules don\'t generate valid recurrence instances');
}
} else {
$noOccurrenceCounter = 0;
}

foreach ($occurrences as $occurrence) {

Expand Down
39 changes: 39 additions & 0 deletions tests/VObject/Recur/EventIterator/InfiniteLoopProblemTest.php
Expand Up @@ -7,6 +7,7 @@
use PHPUnit\Framework\TestCase;
use Sabre\VObject\Component\VCalendar;
use Sabre\VObject\Recur;
use Sabre\VObject\Reader;

class InfiniteLoopProblemTest extends TestCase {

Expand Down Expand Up @@ -96,4 +97,42 @@ function testZeroInterval() {

}

/**
* Another infinite loop, from Issue #329.
*
* This was triggered due to a BYMONTHDAY rule that was using a value that
* never occurred in the BYMONTH rule.
*
* This bug surfaced similar issues with BYDAY and BYSETPOS.
*
* @expectedException \Sabre\VObject\InvalidDataException
*/
function testBadByMonthday() {

$input = Reader::read(<<<ICS
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//something//DE
CALSCALE:GREGORIAN
X-WR-TIMEZONE:Europe/Berlin
BEGIN:VEVENT
UID:20160103T123422CET-9863LIMv8E
DTSTAMP:20160103T113422Z
DESCRIPTION:important date
DTSTART;TZID=Europe/Berlin:20151231T000000
DTEND;TZID=Europe/Berlin:20151231T235900
RRULE:FREQ=YEARLY;COUNT=6;BYMONTHDAY=31;BYMONTH=11
SUMMARY:important date
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR
ICS
);
$input->expand(
new DateTimeImmutable('2015-01-01'),
new DateTimeImmutable('2016-01-01')
);

}

}

0 comments on commit 19f3c45

Please sign in to comment.