summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2021-09-02 17:42:39 +0200
committerAllen Winter <allen.winter@kdab.com>2021-09-18 09:20:27 -0400
commit9e5a5edb2f3ccfc606c9549b87d805c31fef2719 (patch)
tree01949c79828c85e72316a72dc6aa52466dc13f4c /src
parentab7d0531edd28123d50de1ba2cf43fa1262855cb (diff)
downloadlibical-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.c20
-rw-r--r--src/libicalvcal/vcc.y20
-rw-r--r--src/test/regression.c85
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... **/