From: Timo Sirainen Date: Thu, 2 Jul 2020 14:31:19 +0000 (+0300) Subject: lib-mail: Fix handling trailing "--" in MIME boundaries X-Git-Tag: 2.3.11.2~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6001e4b48c5a23735eb9c4ca9a187a175fd1a1da;p=thirdparty%2Fdovecot%2Fcore.git lib-mail: Fix handling trailing "--" in MIME boundaries Broken by 5b8ec27fae941d06516c30476dcf4820c6d200ab --- diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c index 6370a1bff7..011dea9050 100644 --- a/src/lib-mail/message-parser.c +++ b/src/lib-mail/message-parser.c @@ -19,7 +19,7 @@ static int parse_next_body_to_eof(struct message_parser_ctx *ctx, static struct message_boundary * boundary_find(struct message_boundary *boundaries, - const unsigned char *data, size_t len) + const unsigned char *data, size_t len, bool trailing_dashes) { struct message_boundary *best = NULL; @@ -33,7 +33,11 @@ boundary_find(struct message_boundary *boundaries, memcmp(boundaries->boundary, data, boundaries->len) == 0 && (best == NULL || best->len < boundaries->len)) { best = boundaries; - if (best->len == len) { + /* If we see "foo--", it could either mean that there + is a boundary named "foo" that ends now or there's + a boundary "foo--" which continues. */ + if (best->len == len || + (best->len == len-2 && trailing_dashes)) { /* This is exactly the wanted boundary. There can't be a better one. */ break; @@ -261,6 +265,7 @@ boundary_line_find(struct message_parser_ctx *ctx, return 0; } size_t find_size = size; + bool trailing_dashes = FALSE; if (lf_pos != NULL) { find_size = lf_pos - data; @@ -268,11 +273,12 @@ boundary_line_find(struct message_parser_ctx *ctx, find_size--; if (find_size > 2 && data[find_size-1] == '-' && data[find_size-2] == '-') - find_size -= 2; + trailing_dashes = TRUE; } else if (find_size > BOUNDARY_END_MAX_LEN) find_size = BOUNDARY_END_MAX_LEN; - *boundary_r = boundary_find(ctx->boundaries, data, find_size); + *boundary_r = boundary_find(ctx->boundaries, data, find_size, + trailing_dashes); if (*boundary_r == NULL) return -1; diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c index 1b782f5df2..641edec4be 100644 --- a/src/lib-mail/test-message-parser.c +++ b/src/lib-mail/test-message-parser.c @@ -532,6 +532,51 @@ static const char input_msg[] = test_end(); } +static void test_message_parser_trailing_dashes(void) +{ +static const char input_msg[] = +"Content-Type: multipart/mixed; boundary=\"a--\"\n" +"\n" +"--a--\n" +"Content-Type: multipart/mixed; boundary=\"a----\"\n" +"\n" +"--a----\n" +"Content-Type: text/plain\n" +"\n" +"body\n" +"--a------\n" +"Content-Type: text/html\n" +"\n" +"body2\n" +"--a----"; + struct message_parser_ctx *parser; + struct istream *input; + struct message_part *parts; + struct message_block block; + pool_t pool; + int ret; + + test_begin("message parser trailing dashes"); + pool = pool_alloconly_create("message parser", 10240); + input = test_istream_create(input_msg); + + parser = message_parser_init(pool, input, &set_empty); + while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ; + test_assert(ret < 0); + message_parser_deinit(&parser, &parts); + + test_assert(parts->children_count == 2); + test_assert(parts->children->next == NULL); + test_assert(parts->children->children_count == 1); + test_assert(parts->children->children->next == NULL); + test_assert(parts->children->children->children_count == 0); + + test_parsed_parts(input, parts); + i_stream_unref(&input); + pool_unref(&pool); + test_end(); +} + static void test_message_parser_continuing_mime_boundary(void) { static const char input_msg[] = @@ -1095,6 +1140,7 @@ int main(void) test_message_parser_empty_multipart, test_message_parser_duplicate_mime_boundary, test_message_parser_garbage_suffix_mime_boundary, + test_message_parser_trailing_dashes, test_message_parser_continuing_mime_boundary, test_message_parser_continuing_truncated_mime_boundary, test_message_parser_continuing_mime_boundary_reverse,