From a4e981cd2ad9445af24118d33c9613da60a5dd4c Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 22 Dec 2017 18:42:53 +0200 Subject: [PATCH] lib-mail: Make sure parsers don't accidentally go much beyond end pointer --- src/lib-mail/message-address.c | 18 +++++++-------- src/lib-mail/message-date.c | 4 ++-- src/lib-mail/message-part-data.c | 2 +- src/lib-mail/rfc2231-parser.c | 2 +- src/lib-mail/rfc822-parser.c | 38 ++++++++++++++++---------------- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c index d426a16510..a9a09f10ae 100644 --- a/src/lib-mail/message-address.c +++ b/src/lib-mail/message-address.c @@ -85,7 +85,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 == '"') @@ -118,7 +118,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 != '@') @@ -154,7 +154,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 { @@ -204,7 +204,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 ? 1 : 0; + return ctx->parser.data < ctx->parser.end ? 1 : 0; } static int parse_addr_spec(struct message_address_parser_context *ctx) @@ -212,7 +212,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); @@ -222,7 +222,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) @@ -318,7 +318,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++; @@ -329,7 +329,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 { @@ -369,7 +369,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; diff --git a/src/lib-mail/message-date.c b/src/lib-mail/message-date.c index 9fa3823454..a3d1bfd094 100644 --- a/src/lib-mail/message-date.c +++ b/src/lib-mail/message-date.c @@ -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); diff --git a/src/lib-mail/message-part-data.c b/src/lib-mail/message-part-data.c index 88b53ebab0..c9c47b1cc6 100644 --- a/src/lib-mail/message-part-data.c +++ b/src/lib-mail/message-part-data.c @@ -373,7 +373,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); diff --git a/src/lib-mail/rfc2231-parser.c b/src/lib-mail/rfc2231-parser.c index c030eed00d..2f0c796962 100644 --- a/src/lib-mail/rfc2231-parser.c +++ b/src/lib-mail/rfc2231-parser.c @@ -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; diff --git a/src/lib-mail/rfc822-parser.c b/src/lib-mail/rfc822-parser.c index 324b5ba2c3..a0990df947 100644 --- a/src/lib-mail/rfc822-parser.c +++ b/src/lib-mail/rfc822-parser.c @@ -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 ? 1 : 0; + 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 ? 1 : 0; + 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);