View Issue Details

IDProjectCategoryView StatusLast Update
0002274SOGoWeb Calendarpublic2013-03-24 12:08
Reporteravoegele Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Product Version2.0.4b 
Summary0002274: Infinite loop in SOPE/NGCards/iCalTimeZonePeriod.m when importing iCalendar data from last.fm
Description

When importing iCalendar data from last.fm SOGo segfaults because of an infinite loop in [iCalTimeZonePeriod occurrenceForDate:]. There's a note in SOPE/NGCards/iCalTimeZone.m that might refer to this bug:

/ FIXME, this could cause crashes when timezones are not properly
specified, but let's say it won't happen often...
/

The timezones in the last.fm calendars are valid according to RFC 5545, which specifies iCalendar, though.

An iCalendar that can be used to reproduce the bug is attached.

Additional Information

SOGo calls the following methods when importing the last.fm iCalendar data:

[SOGoAppointmentFolder importCalendar:]
[SOGoAppointmentFolder importComponent:timezone:]
[SOGoContentObject saveContentString:]
[GCSFolder writeContent:toName:baseVersion:]
[OCSiCalFieldExtractor extractQuickFieldsFromContent:]
[iCalCalendar parseSingleFromSource:]
[iCalEvent quickRecord]
[iCalEntityObject startDate]
[CardGroup uniqueChildWithTag: @"dtstart"]
[iCalDateTime dateTime:]
[iCalTimeZone dateForDateTimeString:]
[iCalTimeZone periodForDate:]
[iCalTimeZone _occurrenceForPeriodNamed:forDate:]
[iCalTimeZonePeriod occurrenceForDate:]
[CardGroup uniqueChildWithTag: @"dtstart"]
[iCalDateTime dateTime:]
...

I'll add an example program that demonstrate the bug and a patch that fixes the problem for me. The patch replaces the last dateTime call in the above list with code that returns dtstart directly in order to break the infinite loop.

Tagsical

Activities

2013-03-23 18:22

 

lastfm.ics (816 bytes)   
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Last.fm Limited Event Feeds//NONSGML//EN

BEGIN:VTIMEZONE
TZID:Europe/Berlin
BEGIN:STANDARD
TZOFFSETFROM:+0100
TZOFFSETTO:+0100
DTSTART;TZID=Europe/Berlin:20130316T062900
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:LFMEVENT-3486600
URL;VALUE=URI:http://www.last.fm/event/3486600+The+King+Khan+-+BBQ+Show+at+Molotow+on+30+March+2013
DTSTAMP;TZID=Europe/Berlin:20130330T145000
DTSTART;TZID=Europe/Berlin;TZID=Europe/Berlin:20130330T000000
DTEND;TZID=Europe/Berlin;TZID=Europe/Berlin:20130330T235900
SUMMARY:The King Khan & BBQ Show at Molotow
DESCRIPTION:The King Khan & BBQ Show
 \n\nhttp://www.last.fm/event/3486600+The+King+Khan+-+BBQ+Show+at+Molotow+on+30+March+2013
LOCATION:Molotow\, Hamburg\, Germany
GEO:9.9662;53.54941
END:VEVENT

END:VCALENDAR
lastfm.ics (816 bytes)   

2013-03-23 18:23

 

calendar.m (776 bytes)   
// Demonstrates a bug in [iCalTimeZone periodForDate:].

#import <Foundation/Foundation.h>
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalEvent.h>

void parseCalendar(NSString *s)
{
    iCalCalendar *cal;
    iCalEvent *ev;

    // See [OCSiCalFieldExtractor extractQuickFieldsFromContent:].
    cal = [iCalCalendar parseSingleFromSource: s];
    ev = [[cal allObjects] objectAtIndex: 0];
    [ev startDate];
}

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool;
    pool = [NSAutoreleasePool new];

    NSError *error;
    NSString *ical = [NSString
        stringWithContentsOfFile:@"lastfm.ics"
                        encoding:NSUTF8StringEncoding
                           error:&error];
    parseCalendar(ical);

    [pool release];
    return 0;
}
calendar.m (776 bytes)   

2013-03-23 18:23

 

GNUmakefile (265 bytes)   
# GNUstep makefile

debug=yes

include $(GNUSTEP_MAKEFILES)/common.make

TOOL_NAME = calendar

calendar_OBJC_FILES = calendar.m

ADDITIONAL_TOOL_LIBS = -lNGCards

-include GNUmakefile.preamble

include $(GNUSTEP_MAKEFILES)/tool.make

-include GNUmakefile.postamble
GNUmakefile (265 bytes)   

2013-03-23 18:24

 

patch-iCalTimeZonePeriod.diff (856 bytes)   
diff --git a/SOPE/NGCards/iCalTimeZonePeriod.m b/SOPE/NGCards/iCalTimeZonePeriod.m
index a7e2187..074f879 100644
--- a/SOPE/NGCards/iCalTimeZonePeriod.m
+++ b/SOPE/NGCards/iCalTimeZonePeriod.m
@@ -189,8 +189,13 @@
   rrule = (iCalRecurrenceRule *) [self uniqueChildWithTag: @"rrule"];
 
   if ([rrule isVoid])
-    tmpDate
-      = [(iCalDateTime *) [self uniqueChildWithTag: @"dtstart"] dateTime];
+    {
+      /* This function used to call [iCalDateTime dateTime] but that may
+         cause infinite loops. */
+      NSString *date = [[[self uniqueChildWithTag: @"dtstart"] valuesAtIndex: 0 forKey: @""] lastObject];
+      if (date)
+        tmpDate = [date asCalendarDate];
+    }
   else if ([rrule untilDate] == nil || [refDate compare: [rrule untilDate]] == NSOrderedAscending)
     tmpDate = [self _occurrenceForDate: refDate byRRule: rrule];
 
avoegele

avoegele

2013-03-24 12:08

reporter   ~0005434

My patch breaks the infinite loop but the times of the imported events are shifted one hour into the future.

Issue History

Date Modified Username Field Change
2013-03-23 18:22 avoegele New Issue
2013-03-23 18:22 avoegele File Added: lastfm.ics
2013-03-23 18:23 avoegele File Added: calendar.m
2013-03-23 18:23 avoegele File Added: GNUmakefile
2013-03-23 18:24 avoegele File Added: patch-iCalTimeZonePeriod.diff
2013-03-23 18:26 avoegele Tag Attached: ical
2013-03-24 12:08 avoegele Note Added: 0005434