]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Make sure parsers don't accidentally go much beyond end pointer
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 22 Dec 2017 16:42:53 +0000 (18:42 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 6 Mar 2018 10:51:24 +0000 (12:51 +0200)
src/lib-mail/message-address.c
src/lib-mail/message-date.c
src/lib-mail/message-part-data.c
src/lib-mail/rfc2231-parser.c
src/lib-mail/rfc822-parser.c

index 787a26e017879182d880e6fa22f8bea4e99006fd..88d638a42a69884bcad6600a7c9ad51650b14526 100644 (file)
@@ -84,7 +84,7 @@ static int parse_local_part(struct message_address_parser_context *ctx)
           local-part      = dot-atom / quoted-string / obs-local-part
           obs-local-part  = word *("." word)
        */
-       i_assert(ctx->parser.data != ctx->parser.end);
+       i_assert(ctx->parser.data < ctx->parser.end);
 
        str_truncate(ctx->str, 0);
        if (*ctx->parser.data == '"')
@@ -117,7 +117,7 @@ static int parse_domain_list(struct message_address_parser_context *ctx)
        /* obs-domain-list = "@" domain *(*(CFWS / "," ) [CFWS] "@" domain) */
        str_truncate(ctx->str, 0);
        for (;;) {
-               if (ctx->parser.data == ctx->parser.end)
+               if (ctx->parser.data >= ctx->parser.end)
                        return 0;
 
                if (*ctx->parser.data != '@')
@@ -153,7 +153,7 @@ static int parse_angle_addr(struct message_address_parser_context *ctx)
                if (parse_domain_list(ctx) <= 0 || *ctx->parser.data != ':') {
                        if (ctx->fill_missing)
                                ctx->addr.route = "INVALID_ROUTE";
-                       if (ctx->parser.data == ctx->parser.end)
+                       if (ctx->parser.data >= ctx->parser.end)
                                return -1;
                        /* try to continue anyway */
                } else {
@@ -203,7 +203,7 @@ static int parse_name_addr(struct message_address_parser_context *ctx)
                        ctx->addr.domain = "SYNTAX_ERROR";
                ctx->addr.invalid_syntax = TRUE;
        }
-       return ctx->parser.data != ctx->parser.end;
+       return ctx->parser.data < ctx->parser.end ? 1 : 0;
 }
 
 static int parse_addr_spec(struct message_address_parser_context *ctx)
@@ -211,7 +211,7 @@ static int parse_addr_spec(struct message_address_parser_context *ctx)
        /* addr-spec       = local-part "@" domain */
        int ret, ret2 = -2;
 
-       i_assert(ctx->parser.data != ctx->parser.end);
+       i_assert(ctx->parser.data < ctx->parser.end);
 
        str_truncate(ctx->parser.last_comment, 0);
 
@@ -221,7 +221,7 @@ static int parse_addr_spec(struct message_address_parser_context *ctx)
                /* end of input or parsing local-part failed */
                ctx->addr.invalid_syntax = TRUE;
        }
-       if (ret != 0 && ctx->parser.data != ctx->parser.end &&
+       if (ret != 0 && ctx->parser.data < ctx->parser.end &&
            *ctx->parser.data == '@') {
                ret2 = parse_domain(ctx);
                if (ret2 <= 0)
@@ -317,7 +317,7 @@ static int parse_group(struct message_address_parser_context *ctx)
                        if (parse_mailbox(ctx) <= 0) {
                                /* broken mailbox - try to continue anyway. */
                        }
-                       if (ctx->parser.data == ctx->parser.end ||
+                       if (ctx->parser.data >= ctx->parser.end ||
                            *ctx->parser.data != ',')
                                break;
                        ctx->parser.data++;
@@ -328,7 +328,7 @@ static int parse_group(struct message_address_parser_context *ctx)
                }
        }
        if (ret >= 0) {
-               if (ctx->parser.data == ctx->parser.end ||
+               if (ctx->parser.data >= ctx->parser.end ||
                    *ctx->parser.data != ';')
                        ret = -1;
                else {
@@ -368,7 +368,7 @@ static int parse_address_list(struct message_address_parser_context *ctx,
                max_addresses--;
                if ((ret = parse_address(ctx)) == 0)
                        break;
-               if (ctx->parser.data == ctx->parser.end ||
+               if (ctx->parser.data >= ctx->parser.end ||
                    *ctx->parser.data != ',') {
                        ret = -1;
                        break;
index e6956b7cde4bfd76bccc9d7d3e12c71e777c2d17..b67b21e30c193c839400b8b6a40c41d976be8288 100644 (file)
@@ -103,7 +103,7 @@ static int next_token(struct message_date_parser_context *ctx,
        int ret;
 
        str_truncate(ctx->str, 0);
-       ret = ctx->parser.data == ctx->parser.end ? 0 :
+       ret = ctx->parser.data >= ctx->parser.end ? 0 :
                rfc822_parse_atom(&ctx->parser, ctx->str);
 
        *value = str_data(ctx->str);
@@ -205,7 +205,7 @@ message_date_parser_tokens(struct message_date_parser_context *ctx,
        tm.tm_min = (value[0]-'0') * 10 + (value[1]-'0');
 
        /* [:ss] */
-       if (ctx->parser.data != ctx->parser.end &&
+       if (ctx->parser.data < ctx->parser.end &&
            IS_TIME_SEP(*ctx->parser.data)) {
                ctx->parser.data++;
                rfc822_skip_lwsp(&ctx->parser);
index 75651a2892499729f17ce6a733ff52c600433c95..7f13244d1146d55201fd84f7f969b67e38ed4e28 100644 (file)
@@ -374,7 +374,7 @@ parse_content_language(struct message_part_data *data,
                array_append(&langs, &lang, 1);
                str_truncate(str, 0);
 
-               if (parser.data == parser.end || *parser.data != ',')
+               if (parser.data >= parser.end || *parser.data != ',')
                        break;
                parser.data++;
                rfc822_skip_lwsp(&parser);
index f62326e613e965e4b0591904e0edeffc89ea5729..c65b7982149fc8ae9ec1dea1e897fbe353fac11c 100644 (file)
@@ -59,7 +59,7 @@ int rfc2231_parse(struct rfc822_parser_context *ctx,
                if (ret < 0) {
                        /* try to continue anyway.. */
                        broken = TRUE;
-                       if (ctx->data == ctx->end)
+                       if (ctx->data >= ctx->end)
                                break;
                        ctx->data++;
                        continue;
index edb07f52d43b8725c296a1b6e8c6429bfe4a1880..4e7a86d071cafe58b16b94c85c0c228249ad70d8 100644 (file)
@@ -72,7 +72,7 @@ int rfc822_skip_comment(struct rfc822_parser_context *ctx)
                str_truncate(ctx->last_comment, 0);
 
        start = ++ctx->data;
-       for (; ctx->data != ctx->end; ctx->data++) {
+       for (; ctx->data < ctx->end; ctx->data++) {
                switch (*ctx->data) {
                case '(':
                        level++;
@@ -84,7 +84,7 @@ int rfc822_skip_comment(struct rfc822_parser_context *ctx)
                                                     ctx->data - start);
                                }
                                ctx->data++;
-                               return ctx->data != ctx->end;
+                               return ctx->data < ctx->end ? 1 : 0;
                        }
                        break;
                case '\\':
@@ -95,7 +95,7 @@ int rfc822_skip_comment(struct rfc822_parser_context *ctx)
                        start = ctx->data + 1;
 
                        ctx->data++;
-                       if (ctx->data == ctx->end)
+                       if (ctx->data >= ctx->end)
                                return -1;
                        break;
                }
@@ -107,7 +107,7 @@ int rfc822_skip_comment(struct rfc822_parser_context *ctx)
 
 int rfc822_skip_lwsp(struct rfc822_parser_context *ctx)
 {
-       for (; ctx->data != ctx->end;) {
+       for (; ctx->data < ctx->end;) {
                if (*ctx->data == ' ' || *ctx->data == '\t' ||
                    *ctx->data == '\r' || *ctx->data == '\n') {
                         ctx->data++;
@@ -120,7 +120,7 @@ int rfc822_skip_lwsp(struct rfc822_parser_context *ctx)
                if (rfc822_skip_comment(ctx) < 0)
                        return -1;
        }
-       return ctx->data != ctx->end;
+       return ctx->data < ctx->end ? 1 : 0;
 }
 
 int rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str)
@@ -132,10 +132,10 @@ int rfc822_parse_atom(struct rfc822_parser_context *ctx, string_t *str)
           atext           =
             ; Any character except controls, SP, and specials.
        */
-       if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
+       if (ctx->data >= ctx->end || !IS_ATEXT(*ctx->data))
                return -1;
 
-       for (start = ctx->data++; ctx->data != ctx->end; ctx->data++) {
+       for (start = ctx->data++; ctx->data < ctx->end; ctx->data++) {
                if (IS_ATEXT(*ctx->data))
                        continue;
 
@@ -161,10 +161,10 @@ int rfc822_parse_dot_atom(struct rfc822_parser_context *ctx, string_t *str)
 
           For RFC-822 compatibility allow LWSP around '.'
        */
-       if (ctx->data == ctx->end || !IS_ATEXT(*ctx->data))
+       if (ctx->data >= ctx->end || !IS_ATEXT(*ctx->data))
                return -1;
 
-       for (start = ctx->data++; ctx->data != ctx->end; ) {
+       for (start = ctx->data++; ctx->data < ctx->end; ) {
                if (IS_ATEXT(*ctx->data)) {
                        ctx->data++;
                        continue;
@@ -194,7 +194,7 @@ int rfc822_parse_mime_token(struct rfc822_parser_context *ctx, string_t *str)
 {
        const unsigned char *start;
 
-       for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
+       for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
                if (IS_ATEXT_NON_TSPECIAL(*ctx->data) || *ctx->data == '.')
                        continue;
 
@@ -215,7 +215,7 @@ int rfc822_parse_quoted_string(struct rfc822_parser_context *ctx, string_t *str)
        i_assert(*ctx->data == '"');
        ctx->data++;
 
-       for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
+       for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
                switch (*ctx->data) {
                case '"':
                        str_append_n(str, start, ctx->data - start);
@@ -231,7 +231,7 @@ int rfc822_parse_quoted_string(struct rfc822_parser_context *ctx, string_t *str)
                        break;
                case '\\':
                        ctx->data++;
-                       if (ctx->data == ctx->end)
+                       if (ctx->data >= ctx->end)
                                return -1;
 
                        str_append_n(str, start, ctx->data - start - 1);
@@ -257,7 +257,7 @@ rfc822_parse_atom_or_dot(struct rfc822_parser_context *ctx, string_t *str)
           The difference between this function and rfc822_parse_dot_atom()
           is that this doesn't just silently skip over all the whitespace.
        */
-       for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
+       for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
                if (IS_ATEXT(*ctx->data) || *ctx->data == '.')
                        continue;
 
@@ -279,7 +279,7 @@ int rfc822_parse_phrase(struct rfc822_parser_context *ctx, string_t *str)
           obs-phrase = word *(word / "." / CFWS)
        */
 
-       if (ctx->data == ctx->end)
+       if (ctx->data >= ctx->end)
                return 0;
        if (*ctx->data == '.')
                return -1;
@@ -317,10 +317,10 @@ rfc822_parse_domain_literal(struct rfc822_parser_context *ctx, string_t *str)
        i_assert(ctx->data < ctx->end);
        i_assert(*ctx->data == '[');
 
-       for (start = ctx->data; ctx->data != ctx->end; ctx->data++) {
+       for (start = ctx->data; ctx->data < ctx->end; ctx->data++) {
                if (*ctx->data == '\\') {
                        ctx->data++;
-                       if (ctx->data == ctx->end)
+                       if (ctx->data >= ctx->end)
                                break;
                } else if (*ctx->data == ']') {
                        ctx->data++;
@@ -389,7 +389,7 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
        *key_r = NULL;
        *value_r = NULL;
 
-       if (ctx->data == ctx->end)
+       if (ctx->data >= ctx->end)
                return 0;
        if (*ctx->data != ';')
                return -1;
@@ -412,10 +412,10 @@ int rfc822_parse_content_param(struct rfc822_parser_context *ctx,
                /* broken / no value */
        } else if (*ctx->data == '"') {
                ret = rfc822_parse_quoted_string(ctx, tmp);
-       } else if (ctx->data != ctx->end && *ctx->data == '=') {
+       } else if (ctx->data < ctx->end && *ctx->data == '=') {
                /* workaround for broken input:
                   name==?utf-8?b?...?= */
-               while (ctx->data != ctx->end && *ctx->data != ';' &&
+               while (ctx->data < ctx->end && *ctx->data != ';' &&
                       *ctx->data != ' ' && *ctx->data != '\t' &&
                       *ctx->data != '\r' && *ctx->data != '\n') {
                        str_append_c(tmp, *ctx->data);