diff options
author | Milan Crha <mcrha@redhat.com> | 2021-09-02 17:42:39 +0200 |
---|---|---|
committer | Allen Winter <allen.winter@kdab.com> | 2021-09-18 09:20:27 -0400 |
commit | 9e5a5edb2f3ccfc606c9549b87d805c31fef2719 (patch) | |
tree | 01949c79828c85e72316a72dc6aa52466dc13f4c /src | |
parent | ab7d0531edd28123d50de1ba2cf43fa1262855cb (diff) | |
download | libical-git-9e5a5edb2f3ccfc606c9549b87d805c31fef2719.tar.gz |
libicalvcal: Cast EOF to 'char' to ensure matching its value against it
Some arches (like aarch64, ppc64le and s390x) may not match the EOF
constant against its value cast to 'char'. That breaks the parser and
can cause an indefinite read of the content, with growing memory use.
Diffstat (limited to 'src')
-rw-r--r-- | src/libicalvcal/vcc.c | 20 | ||||
-rw-r--r-- | src/libicalvcal/vcc.y | 20 | ||||
-rw-r--r-- | src/test/regression.c | 85 |
3 files changed, 105 insertions, 20 deletions
diff --git a/src/libicalvcal/vcc.c b/src/libicalvcal/vcc.c index 44068d16..3eb80d2c 100644 --- a/src/libicalvcal/vcc.c +++ b/src/libicalvcal/vcc.c @@ -607,7 +607,7 @@ static int lexGeta_(int i) } static void lexSkipLookahead() { - if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) { /* don't skip EOF. */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; @@ -642,7 +642,7 @@ static int lexLookahead() { static int lexGetc() { int c = lexLookahead(); - if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) { /* EOF will remain in lookahead buffer */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; @@ -692,7 +692,7 @@ static char* lexGetWord() { lexSkipWhite(); lexClearToken(); c = lexLookahead(); - while (c != EOF && !strchr("\t\n ;:=",c)) { + while (c != ((char) EOF) && !strchr("\t\n ;:=",c)) { lexAppendc(c); lexSkipLookahead(); c = lexLookahead(); @@ -704,7 +704,7 @@ static char* lexGetWord() { static void lexPushLookaheadc(int c) { int putptr; /* can't putback EOF, because it never leaves lookahead buffer */ - if (c == EOF) return; + if (((char) c) == ((char) EOF)) return; putptr = (int)lexBuf.getPtr - 1; if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; lexBuf.getPtr = (unsigned long)putptr; @@ -726,7 +726,7 @@ static char* lexLookaheadWord() { while (len < (MAX_LEX_LOOKAHEAD_0)) { c = lexGetc(); len++; - if (c == EOF || strchr("\t\n ;:=", c)) { + if (c == ((char) EOF) || strchr("\t\n ;:=", c)) { lexAppendc(0); /* restore lookahead buf. */ lexBuf.len += len; @@ -783,7 +783,7 @@ static char* lexGet1Value() { lexSkipWhite(); c = lexLookahead(); lexClearToken(); - while (c != EOF && c != ';') { + while (c != ((char) EOF) && c != ';') { if (c == '\n') { int a; lexSkipLookahead(); @@ -805,7 +805,7 @@ static char* lexGet1Value() { } lexAppendc(0); handleMoreRFC822LineBreak(c); - return c==EOF?0:lexStr(); + return c==((char) EOF)?0:lexStr(); } #endif @@ -903,9 +903,9 @@ static char * lexGetDataFromBase64() else if (oldBytes) free(oldBytes); /* error recovery: skip until 2 adjacent newlines. */ DBG_(("db: invalid character 0x%x '%c'\n", c,c)); - if (c != EOF) { + if (c != ((char) EOF)) { c = lexGetc(); - while (c != EOF) { + while (c != ((char) EOF)) { if (c == '\n' && lexLookahead() == '\n') { ++mime_lineNum; break; @@ -1123,7 +1123,7 @@ int yylex() { ++mime_lineNum; continue; } - case EOF: return 0; + case ((char) EOF): return 0; break; default: { lexPushLookaheadc(c); diff --git a/src/libicalvcal/vcc.y b/src/libicalvcal/vcc.y index 3280a035..834f6b98 100644 --- a/src/libicalvcal/vcc.y +++ b/src/libicalvcal/vcc.y @@ -573,7 +573,7 @@ static int lexGeta_(int i) } static void lexSkipLookahead() { - if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) { /* don't skip EOF. */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; @@ -608,7 +608,7 @@ static int lexLookahead() { static int lexGetc() { int c = lexLookahead(); - if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { + if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=((char) EOF)) { /* EOF will remain in lookahead buffer */ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; lexBuf.len--; @@ -658,7 +658,7 @@ static char* lexGetWord() { lexSkipWhite(); lexClearToken(); c = lexLookahead(); - while (c != EOF && !strchr("\t\n ;:=",c)) { + while (c != ((char) EOF) && !strchr("\t\n ;:=",c)) { lexAppendc(c); lexSkipLookahead(); c = lexLookahead(); @@ -670,7 +670,7 @@ static char* lexGetWord() { static void lexPushLookaheadc(int c) { int putptr; /* can't putback EOF, because it never leaves lookahead buffer */ - if (c == EOF) return; + if (((char) c) == ((char) EOF)) return; putptr = (int)lexBuf.getPtr - 1; if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; lexBuf.getPtr = putptr; @@ -692,7 +692,7 @@ static char* lexLookaheadWord() { while (len < (MAX_LEX_LOOKAHEAD_0)) { c = lexGetc(); len++; - if (c == EOF || strchr("\t\n ;:=", c)) { + if (c == ((char) EOF) || strchr("\t\n ;:=", c)) { lexAppendc(0); /* restore lookahead buf. */ lexBuf.len += len; @@ -749,7 +749,7 @@ static char* lexGet1Value() { lexSkipWhite(); c = lexLookahead(); lexClearToken(); - while (c != EOF && c != ';') { + while (c != ((char) EOF) && c != ';') { if (c == '\n') { int a; lexSkipLookahead(); @@ -771,7 +771,7 @@ static char* lexGet1Value() { } lexAppendc(0); handleMoreRFC822LineBreak(c); - return c==EOF?0:lexStr(); + return c==((char) EOF)?0:lexStr(); } #endif @@ -869,9 +869,9 @@ static char * lexGetDataFromBase64() else if (oldBytes) free(oldBytes); /* error recovery: skip until 2 adjacent newlines. */ DBG_(("db: invalid character 0x%x '%c'\n", c,c)); - if (c != EOF) { + if (c != ((char) EOF)) { c = lexGetc(); - while (c != EOF) { + while (c != ((char) EOF)) { if (c == '\n' && lexLookahead() == '\n') { ++mime_lineNum; break; @@ -1089,7 +1089,7 @@ int yylex() { ++mime_lineNum; continue; } - case EOF: return 0; + case ((char) EOF): return 0; break; default: { lexPushLookaheadc(c); diff --git a/src/test/regression.c b/src/test/regression.c index 12794413..8b9c6392 100644 --- a/src/test/regression.c +++ b/src/test/regression.c @@ -4642,6 +4642,90 @@ static void test_builtin_compat_tzid (void) icaltimezone_free_builtin_timezones(); } +static void test_vcc_vcard_parse (void) +{ + /* Two VCARD-s, because some arches can parse the first and some the second. */ + const char *vcard1 = + "BEGIN:VCARD\r\n" + "VERSION:3.0\r\n" + "NOTE:\r\n" + "FN:Xxxx\r\n" + "N:;Xxxx;;;\r\n" + "END:VCARD"; + const char *vcard2 = + "BEGIN:VCARD\r\n" + "VERSION:3.0\r\n" + "X-XXX-ORIGINAL-VCARD:\r\n" + "X-XXX-KIND:XX_XXXXXXXX\r\n" + "NOTE:\r\n" + "X-XXXXXXXXX-FILE-AS:Xxxxxx\r\n" + "FN:Xxxxxx\r\n" + "N:;Xxxxxx;;;\r\n" + "X-XXX-XXXXXXXXX:\r\n" + "END:VCARD"; + const char *vcalendar = + "BEGIN:VCALENDAR\r\n" + "BEGIN:VEVENT\r\n" + "UID:123\r\n" + "SUMMARY:Summary\r\n" + "DTSTAMP:20210803T063522Z\r\n" + "DTSTART;VALUE=DATE:20210902\r\n" + "END:VEVENT\r\n" + "END:VCALENDAR\r\n"; + VObject *vcal; + + vcal = Parse_MIME(vcard1, strlen(vcard1)); + if(vcal) { + icalcomponent *icalcomp; + + icalcomp = icalvcal_convert (vcal); + ok("vCard1 is not iCalendar", (icalcomp == NULL)); + if(icalcomp) + icalcomponent_free (icalcomp); + + cleanVObject (vcal); + } else { + ok("vCard1 cannot be parsed", (vcal == NULL)); + } + + vcal = Parse_MIME(vcard2, strlen(vcard2)); + if(vcal) { + icalcomponent *icalcomp; + + icalcomp = icalvcal_convert (vcal); + ok("vCard2 is not iCalendar", (icalcomp == NULL)); + if(icalcomp) + icalcomponent_free (icalcomp); + + cleanVObject (vcal); + } else { + ok("vCard2 cannot be parsed", (vcal == NULL)); + } + + vcal = Parse_MIME(vcalendar, strlen(vcalendar)); + ok("vCalendar can be parsed", (vcal != NULL)); + if(vcal) { + icalcomponent *icalcomp; + + icalcomp = icalvcal_convert (vcal); + ok("vCalendar can be converted", (icalcomp != NULL)); + if(icalcomp) { + icalcomponent *child; + + ok("vCalendar is VCALENDAR", (icalcomponent_isa(icalcomp) == ICAL_VCALENDAR_COMPONENT)); + ok("vCalendar has one child", (icalcomponent_count_components(icalcomp, ICAL_ANY_COMPONENT) == 1)); + child = icalcomponent_get_inner(icalcomp); + ok("vCalendar has inner comp", (child != NULL && child != icalcomp)); + ok("vCalendar child is VEVENT", (icalcomponent_isa(child) == ICAL_VEVENT_COMPONENT)); + ok("vCalendar child UID matches", (strcmp(icalcomponent_get_uid(child), "123") == 0)); + ok("vCalendar child SUMMARY matches", (strcmp(icalcomponent_get_summary(child), "Summary") == 0)); + icalcomponent_free (icalcomp); + } + + cleanVObject (vcal); + } +} + int main(int argc, char *argv[]) { #if !defined(HAVE_UNISTD_H) @@ -4780,6 +4864,7 @@ int main(int argc, char *argv[]) test_run("Test icalcomponent_normalize", test_icalcomponent_normalize, do_test, do_header); test_run("Test builtin compat TZID", test_builtin_compat_tzid, do_test, do_header); + test_run("Test VCC vCard parse", test_vcc_vcard_parse, do_test, do_header); /** OPTIONAL TESTS go here... **/ |