]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Fixed inner MIME part boundary being a prefix of outer boundary.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 22 Apr 2016 15:28:20 +0000 (18:28 +0300)
committerGitLab <gitlab@git.dovecot.net>
Fri, 22 Apr 2016 22:43:53 +0000 (01:43 +0300)
src/lib-mail/message-parser.c
src/lib-mail/test-message-parser.c

index e936005d56762e81082a0b79f6af33964327688e..e3e712a298d765bb32d3572c23f7d23cc3462ac7 100644 (file)
@@ -66,19 +66,23 @@ static struct message_boundary *
 boundary_find(struct message_boundary *boundaries,
              const unsigned char *data, size_t len)
 {
+       struct message_boundary *best = NULL;
+
        /* As MIME spec says: search from latest one to oldest one so that we
           don't break if the same boundary is used in nested parts. Also the
           full message line doesn't have to match the boundary, only the
-          beginning. */
+          beginning. However, if there are multiple prefixes whose beginning
+          matches, use the longest matching one. */
        while (boundaries != NULL) {
                if (boundaries->len <= len &&
-                   memcmp(boundaries->boundary, data, boundaries->len) == 0)
-                       return boundaries;
+                   memcmp(boundaries->boundary, data, boundaries->len) == 0 &&
+                   (best == NULL || best->len < boundaries->len))
+                       best = boundaries;
 
                boundaries = boundaries->next;
        }
 
-       return NULL;
+       return best;
 }
 
 static void parse_body_add_block(struct message_parser_ctx *ctx,
index 7f7e7b060fe798fecc41cb55fd8cb00affa75ef5..c613bb5306491b22dd35f883d4a48ef9f1dfdf4f 100644 (file)
@@ -196,6 +196,100 @@ static const char input_msg[] =
        test_end();
 }
 
+static void test_message_parser_truncated_mime_headers2(void)
+{
+static const char input_msg[] =
+"Content-Type: multipart/mixed; boundary=\"ab\"\n"
+"\n"
+"--ab\n"
+"Content-Type: multipart/mixed; boundary=\"a\"\n"
+"\n"
+"--ab\n"
+"Content-Type: text/plain\n"
+"\n"
+"--a\n\n";
+       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 truncated mime headers 2");
+       pool = pool_alloconly_create("message parser", 10240);
+       input = test_istream_create(input_msg);
+
+       parser = message_parser_init(pool, input, 0, 0);
+       while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
+       test_assert(ret < 0);
+       test_assert(message_parser_deinit(&parser, &parts) == 0);
+
+       test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(parts->header_size.lines == 2);
+       test_assert(parts->header_size.physical_size == 46);
+       test_assert(parts->header_size.virtual_size == 46+2);
+       test_assert(parts->body_size.lines == 8);
+       test_assert(parts->body_size.physical_size == 86);
+       test_assert(parts->body_size.virtual_size == 86+8);
+
+       test_assert(parts->children->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(parts->children->physical_pos == 51);
+       test_assert(parts->children->header_size.lines == 1);
+       test_assert(parts->children->header_size.physical_size == 44);
+       test_assert(parts->children->header_size.virtual_size == 44+1);
+       test_assert(parts->children->body_size.lines == 0);
+       test_assert(parts->children->body_size.physical_size == 0);
+       test_assert(parts->children->children == NULL);
+
+       test_assert(parts->children->next->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(parts->children->next->physical_pos == 101);
+       test_assert(parts->children->next->header_size.lines == 2);
+       test_assert(parts->children->next->header_size.physical_size == 26);
+       test_assert(parts->children->next->header_size.virtual_size == 26+2);
+       test_assert(parts->children->next->body_size.lines == 2);
+       test_assert(parts->children->next->body_size.physical_size == 5);
+       test_assert(parts->children->next->body_size.virtual_size == 5+2);
+       test_assert(parts->children->next->children == NULL);
+
+       i_stream_unref(&input);
+       pool_unref(&pool);
+       test_end();
+}
+
+static void test_message_parser_truncated_mime_headers3(void)
+{
+static const char input_msg[] =
+"Content-Type: multipart/mixed; boundary=\"ab\"\n";
+       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 truncated mime headers 3");
+       pool = pool_alloconly_create("message parser", 10240);
+       input = test_istream_create(input_msg);
+
+       parser = message_parser_init(pool, input, 0, 0);
+       while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
+       test_assert(ret < 0);
+       test_assert(message_parser_deinit(&parser, &parts) == 0);
+
+       test_assert(parts->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(parts->header_size.lines == 1);
+       test_assert(parts->header_size.physical_size == 45);
+       test_assert(parts->header_size.virtual_size == 45+1);
+       test_assert(parts->body_size.lines == 0);
+       test_assert(parts->body_size.physical_size == 0);
+
+       test_assert(parts->children == NULL);
+
+       i_stream_unref(&input);
+       pool_unref(&pool);
+       test_end();
+}
+
 static void test_message_parser_duplicate_mime_boundary(void)
 {
 static const char input_msg[] =
@@ -342,6 +436,8 @@ int main(void)
        static void (*test_functions[])(void) = {
                test_message_parser_small_blocks,
                test_message_parser_truncated_mime_headers,
+               test_message_parser_truncated_mime_headers2,
+               test_message_parser_truncated_mime_headers3,
                test_message_parser_duplicate_mime_boundary,
                test_message_parser_continuing_mime_boundary,
                test_message_parser_no_eoh,