Skip to content

Commit

Permalink
message: make some strcmps "safe"
Browse files Browse the repository at this point in the history
This fixes crashers with parsing malformed MESSAGE/RFC822
  • Loading branch information
brong committed Jan 21, 2025
1 parent e187b6d commit 3a731bc
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 42 deletions.
27 changes: 15 additions & 12 deletions imap/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ EXPORTED int index_store(struct index_state *state, const char *sequence,
mailbox = state->mailbox;

seq = _parse_sequence(state, sequence, storeargs->usinguid);
if (!strcmp("$", sequence)) {
if (!strcmpsafe("$", sequence)) {
storeargs->usinguid = 1;

if (!seqset_first(seq)) {
Expand Down Expand Up @@ -2764,7 +2764,7 @@ EXPORTED int index_snippets(struct index_state *state,
for ( ; snippetargs ; snippetargs = snippetargs->next) {

mailbox = NULL;
if (!strcmp(snippetargs->mboxname, index_mboxname(state))) {
if (!strcmpsafe(snippetargs->mboxname, index_mboxname(state))) {
mailbox = state->mailbox;
}
else {
Expand Down Expand Up @@ -5761,17 +5761,17 @@ static int getsearchtext_cb(int isbody, charset_t charset, int encoding,

/* Index attachment file names */
const struct param *param;
if (disposition && !strcmp(disposition, "ATTACHMENT")) {
if (disposition && !strcmpsafe(disposition, "ATTACHMENT")) {
/* Look for "Content-Disposition: attachment;filename=" header */
for (param = disposition_params; param; param = param->next) {
if (!strcmp(param->attribute, "FILENAME")) {
if (!strcmpsafe(param->attribute, "FILENAME")) {
char *tmp = charset_decode_mimeheader(param->value, str->charset_flags);
buf_init_ro_cstr(&text, tmp);
stuff_converted_part(str->receiver, SEARCH_PART_ATTACHMENTNAME, &text);
buf_free(&text);
free(tmp);
}
else if (!strcmp(param->attribute, "FILENAME*")) {
else if (!strcmpsafe(param->attribute, "FILENAME*")) {
char *xval = charset_parse_mimexvalue(param->value, NULL);
if (!xval) xval = xstrdup(param->value);
if (xval) {
Expand All @@ -5787,7 +5787,7 @@ static int getsearchtext_cb(int isbody, charset_t charset, int encoding,
}
for(param = type_params; param; param = param->next) {
/* Look for "Content-Type: foo;name=" header */
if (strcmp(param->attribute, "NAME"))
if (strcmpsafe(param->attribute, "NAME"))
continue;
char *tmp = charset_decode_mimeheader(param->value, str->charset_flags);
buf_init_ro_cstr(&text, tmp);
Expand All @@ -5802,16 +5802,16 @@ static int getsearchtext_cb(int isbody, charset_t charset, int encoding,
/* PGP encrypted body part - we don't want to index this,
* it's a ton of random base64 noise */
}
else if (isbody && !strcmp(type, "TEXT") && strcmpsafe(subtype, "RTF")) {
else if (isbody && !strcmpsafe(type, "TEXT") && strcmpsafe(subtype, "RTF")) {

if (str->snippet_iteration >= 2) goto done;

if (!strcmp(subtype, "CALENDAR")) {
if (!strcmpsafe(subtype, "CALENDAR")) {
#ifdef USE_HTTPD
extract_icalbuf(data, charset, encoding, str);
#endif /* USE_HTTPD */
}
else if (!strcmp(subtype, "VCARD")) {
else if (!strcmpsafe(subtype, "VCARD")) {
#ifdef USE_HTTPD
extract_vcardbuf(data, charset, encoding, str);
#endif /* USE_HTTPD */
Expand All @@ -5837,7 +5837,7 @@ static int getsearchtext_cb(int isbody, charset_t charset, int encoding,
}
}
#ifdef USE_HTTPD
else if (isbody && (!strcmp(type, "APPLICATION") && !strcmp(subtype, "ICS"))) {
else if (isbody && (!strcmpsafe(type, "APPLICATION") && !strcmpsafe(subtype, "ICS"))) {
// application/ics is an alias for text/icalendar
extract_icalbuf(data, charset, encoding, str);
}
Expand Down Expand Up @@ -6097,9 +6097,12 @@ EXPORTED int index_getsearchtext(message_t *msg, const strarray_t *partids,

if (!message_get_leaf_types(msg, &types) && types.count) {
for (i = 0 ; i < types.count ; i+= 2) {
if (!types.data[i]) continue;
buf_setcstr(&buf, types.data[i]);
buf_putc(&buf, '/');
buf_appendcstr(&buf, types.data[i+1]);
if (types.data[i+1]) {
buf_putc(&buf, '/');
buf_appendcstr(&buf, types.data[i+1]);
}
stuff_part(receiver, str.conv, SEARCH_PART_TYPE, &buf);
}
}
Expand Down
59 changes: 29 additions & 30 deletions imap/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,9 +657,9 @@ static void message_find_part(struct body *body, const char *section,
int encoding;
charset_t charset = CHARSET_UNKNOWN_CHARSET;
message_parse_charset(body, &encoding, &charset);
if (!strcasecmp(body->type, "text") &&
(!strcasecmp(body->subtype, "calendar") ||
!strcasecmp(body->subtype, "vcard"))) {
if (!strcasecmpsafe(body->type, "text") &&
(!strcasecmpsafe(body->subtype, "calendar") ||
!strcasecmpsafe(body->subtype, "vcard"))) {
/* override charset for text/calendar and text/vcard */
charset_free(&charset);
charset = charset_lookupname("utf-8");
Expand All @@ -681,7 +681,7 @@ static void message_find_part(struct body *body, const char *section,
(*parts)[*n]->decoded_body = body->decoded_body;
(*parts)[++(*n)] = NULL;
}
else if (!strcmp(body->type, "MULTIPART")) {
else if (!strcmpsafe(body->type, "MULTIPART")) {
int i;

for (i = 0; i < body->numparts; i++) {
Expand Down Expand Up @@ -800,7 +800,7 @@ static int message_parse_body(struct msg *msg, struct body *body,
* bodystructure, but we don't have that one here. */
body->charset_id = NULL;
if (body->params) {
charset_t cs = !strcmp(body->type, "TEXT") ?
charset_t cs = !strcmpsafe(body->type, "TEXT") ?
charset_lookupname("us-ascii") : CHARSET_UNKNOWN_CHARSET;
message_parse_charset_params(body->params, &cs);
if (cs != CHARSET_UNKNOWN_CHARSET) {
Expand All @@ -813,7 +813,7 @@ static int message_parse_body(struct msg *msg, struct body *body,
body->charset_enc = encoding_lookupname(body->encoding);

/* Recurse according to type */
if (strcmp(body->type, "MULTIPART") == 0) {
if (strcmpsafe(body->type, "MULTIPART") == 0) {
if (!sawboundary) {
message_parse_multipart(msg, body, boundaries, efname);
}
Expand Down Expand Up @@ -1125,7 +1125,7 @@ EXPORTED void message_parse_charset_params(const struct param *params,
{
const struct param *param;
for (param = params; param; param = param->next) {
if (!strcasecmp(param->attribute, "charset")) {
if (!strcasecmpsafe(param->attribute, "charset")) {
if (param->value && *param->value) {
charset_t cs = charset_lookupname(param->value);
if (cs == CHARSET_UNKNOWN_CHARSET) {
Expand Down Expand Up @@ -1182,9 +1182,9 @@ static void message_parse_charset(const struct body *body,
if (!body->type || !strcmp(body->type, "TEXT")) {
message_parse_charset_params(body->params, &charset);
}
else if (!strcmp(body->type, "MESSAGE")) {
if (!strcmp(body->subtype, "RFC822") ||
!strcmp(body->subtype, "GLOBAL")) {
else if (!strcmpsafe(body->type, "MESSAGE")) {
if (!strcmpsafe(body->subtype, "RFC822") ||
!strcmpsafe(body->subtype, "GLOBAL")) {
charset_free(&charset);
charset = CHARSET_UNKNOWN_CHARSET;
}
Expand Down Expand Up @@ -1840,15 +1840,15 @@ static void message_parse_multipart(struct msg *msg, struct body *body,

memset(&preamble, 0, sizeof(struct body));
memset(&epilogue, 0, sizeof(struct body));
if (strcmp(body->subtype, "DIGEST") == 0) {
if (strcmpsafe(body->subtype, "DIGEST") == 0) {
defaultContentType = "MESSAGE/RFC822";
}

/* Find boundary id */
boundary = body->params;
while (boundary &&
strcmp(boundary->attribute, "BOUNDARY") != 0 &&
strcmp(boundary->attribute, "BOUNDARY*") != 0) {
strcmpsafe(boundary->attribute, "BOUNDARY") != 0 &&
strcmpsafe(boundary->attribute, "BOUNDARY*") != 0) {
boundary = boundary->next;
}

Expand Down Expand Up @@ -1962,8 +1962,7 @@ static void message_parse_content(struct msg *msg, struct body *body,
int len;

/* Should we encode a binary part? */
encode = msg->encode &&
body->encoding && !strcasecmp(body->encoding, "binary");
encode = msg->encode && !strcasecmpsafe(body->encoding, "binary");

while (msg->offset < msg->len) {
line = msg->base + msg->offset;
Expand Down Expand Up @@ -2245,7 +2244,7 @@ EXPORTED void message_write_body(struct buf *buf, const struct body *body,
{
struct param *param;

if (strcmp(body->type, "MULTIPART") == 0) {
if (strcmpsafe(body->type, "MULTIPART") == 0) {
int i;

/* 0-part multiparts are illegal--convert to 0-len text parts */
Expand Down Expand Up @@ -2354,7 +2353,7 @@ EXPORTED void message_write_body(struct buf *buf, const struct body *body,
buf_putc(buf, ' ');
buf_printf(buf, "%u", body->content_size);

if (strcmp(body->type, "TEXT") == 0) {
if (strcmpsafe(body->type, "TEXT") == 0) {
/* Text types get a line count */
buf_putc(buf, ' ');
buf_printf(buf, "%u", body->content_lines);
Expand Down Expand Up @@ -2566,7 +2565,7 @@ static void message_write_section(struct buf *buf, const struct body *body)
buf_appendbit32(buf, body->subpart->subpart[part].header_size);
buf_appendbit32(buf, body->subpart->subpart[part].content_offset);
if (body->subpart->subpart[part].numparts == 0 &&
strcmp(body->subpart->subpart[part].type, "MULTIPART") == 0) {
strcmpsafe(body->subpart->subpart[part].type, "MULTIPART") == 0) {
/* Treat 0-part multipart as 0-length text */
buf_appendbit32(buf, 0);
}
Expand Down Expand Up @@ -2594,7 +2593,7 @@ static void message_write_section(struct buf *buf, const struct body *body)
buf_appendbit32(buf, body->subpart->header_offset);
buf_appendbit32(buf, body->subpart->header_size);
buf_appendbit32(buf, body->subpart->content_offset);
if (strcmp(body->subpart->type, "MULTIPART") == 0) {
if (strcmpsafe(body->subpart->type, "MULTIPART") == 0) {
/* Treat 0-part multipart as 0-length text */
buf_appendbit32(buf, 0);
message_write_nocharset(buf, NULL);
Expand Down Expand Up @@ -2622,7 +2621,7 @@ static void message_write_section(struct buf *buf, const struct body *body)
buf_appendbit32(buf, body->subpart[part].header_size);
buf_appendbit32(buf, body->subpart[part].content_offset);
if (body->subpart[part].numparts == 0 &&
strcmp(body->subpart[part].type, "MULTIPART") == 0) {
strcmpsafe(body->subpart[part].type, "MULTIPART") == 0) {
/* Treat 0-part multipart as 0-length text */
buf_appendbit32(buf, 0);
message_write_nocharset(buf, &body->subpart[part]);
Expand Down Expand Up @@ -3254,15 +3253,15 @@ static int message_read_body(struct protstream *strm, struct body *body, const c
c = getuint32(strm, &body->content_size);
if (c == EOF) goto done;

if (!strcmp(body->type, "TEXT")) {
if (!strcmpsafe(body->type, "TEXT")) {
/* body lines */
c = getuint32(strm, &body->content_lines);
if (c == EOF) goto done;
}
else if ((body_is_rfc822(body) && cache_version >= 13) ||
// Cache versions < 13 only handled message/rfc822.
(!strcmp(body->type, "MESSAGE") &&
!strcmp(body->subtype, "RFC822"))) {
(!strcmpsafe(body->type, "MESSAGE") &&
!strcmpsafe(body->subtype, "RFC822"))) {
body->subpart = (struct body *) xzmalloc(sizeof(struct body));

/* envelope structure */
Expand Down Expand Up @@ -4518,7 +4517,7 @@ static int parse_bodystructure_part(struct protstream *prot, struct body *body,
c = parse_mime_params(prot, &body->params);
if (c != ' ') goto badformat;

if (strcmp(body->type, "MULTIPART")) {
if (strcmpsafe(body->type, "MULTIPART")) {
/* msgid */
c = getnstring(prot, NULL, &buf);
if (c != ' ') goto badformat;
Expand Down Expand Up @@ -4548,8 +4547,8 @@ static int parse_bodystructure_part(struct protstream *prot, struct body *body,

else if ((body_is_rfc822(body) && cache_version >= 13) ||
// Cache versions < 13 only handled message/rfc822.
(!strcasecmp(body->type, "MESSAGE") &&
!strcasecmp(body->subtype, "RFC822"))) {
(!strcasecmpsafe(body->type, "MESSAGE") &&
!strcasecmpsafe(body->subtype, "RFC822"))) {

body->numparts = 1;
body->subpart = xzmalloc(sizeof(struct body));
Expand Down Expand Up @@ -4625,10 +4624,10 @@ static int parse_bodystructure_sections(const char **cachestrp, const char *cach

if ((body_is_rfc822(body) && cache_version >= 13) ||
// Cache versions < 13 only handled message/rfc822.
(!strcasecmp(body->type, "MESSAGE") &&
!strcasecmp(body->subtype, "RFC822"))) {
(!strcasecmpsafe(body->type, "MESSAGE") &&
!strcasecmpsafe(body->subtype, "RFC822"))) {

if (strcmp(body->subpart->type, "MULTIPART") == 0) {
if (strcmpsafe(body->subpart->type, "MULTIPART") == 0) {

/*
* Part 0 of a message/rfc822 is the message header/text.
Expand Down Expand Up @@ -4732,7 +4731,7 @@ static int parse_bodystructure_sections(const char **cachestrp, const char *cach
*cachestrp += 1*4;
*cachestrp += 4*4;

if (strcmp(body->subpart->type, "MULTIPART") == 0) {
if (strcmpsafe(body->subpart->type, "MULTIPART") == 0) {
/* Treat 0-part multipart as 0-length text */
*cachestrp += 1*4;
}
Expand Down

0 comments on commit 3a731bc

Please sign in to comment.