]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Fix handling trailing "--" in MIME boundaries
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 2 Jul 2020 14:31:19 +0000 (17:31 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 2 Jul 2020 19:49:12 +0000 (22:49 +0300)
Broken by 5b8ec27fae941d06516c30476dcf4820c6d200ab

src/lib-mail/message-parser.c
src/lib-mail/test-message-parser.c

index 6370a1bff714be68b34bb5f6bfb405cc3f9ee8bf..011dea9050eb776789c892546e5af2016e66c3b3 100644 (file)
@@ -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;
 
index 1b782f5df2edb858c1ee9f76f8853f7a265b89b1..641edec4be618d074701974910ff360a3df14997 100644 (file)
@@ -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,