]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: message-parser - Fix assert-crash when enforcing MIME part limit
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 11 Sep 2020 06:53:03 +0000 (09:53 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 5 Jan 2021 09:03:52 +0000 (11:03 +0200)
The limit could have been exceeded with message/rfc822 parts.

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

index 6ab4c3266f6271b5c066ba7b7c7818e088ab9840..40a504da0af4d9cbb12d1373405c34fed818f97b 100644 (file)
@@ -703,7 +703,8 @@ static int parse_next_header(struct message_parser_ctx *ctx,
                ctx->multipart = FALSE;
                ctx->parse_next_block = parse_next_body_to_boundary;
        } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) != 0 &&
-                  !parse_too_many_nested_mime_parts(ctx)) {
+                  !parse_too_many_nested_mime_parts(ctx) &&
+                  ctx->total_parts_count < ctx->max_total_mime_parts) {
                ctx->parse_next_block = parse_next_body_message_rfc822_init;
        } else {
                part->flags &= ENUM_NEGATE(MESSAGE_PART_FLAG_MESSAGE_RFC822);
index 8c5a3404f10bdfee7a9b3da346a334d8aebc0428..c4e117afc79d1cb0b401b9d5525181a479a40876 100644 (file)
@@ -1127,6 +1127,87 @@ static const char input_msg[] =
        test_end();
 }
 
+static void test_message_parser_mime_part_limit_rfc822(void)
+{
+static const char input_msg[] =
+"Content-Type: multipart/mixed; boundary=\"1\"\n"
+"\n"
+"--1\n"
+"Content-Type: multipart/mixed; boundary=\"2\"\n"
+"\n"
+"--2\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"1\n"
+"--2\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"22\n"
+"--1\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"Content-Type: text/plain\n"
+"\n"
+"333\n";
+       const struct message_parser_settings parser_set = {
+               .max_total_mime_parts = 3,
+       };
+       struct message_parser_ctx *parser;
+       struct istream *input;
+       struct message_part *parts, *part;
+       struct message_block block;
+       pool_t pool;
+       int ret;
+
+       test_begin("message parser mime part limit rfc822");
+       pool = pool_alloconly_create("message parser", 10240);
+       input = test_istream_create(input_msg);
+
+       parser = message_parser_init(pool, input, &parser_set);
+       while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
+       test_assert(ret < 0);
+       message_parser_deinit(&parser, &parts);
+
+       part = parts;
+       test_assert(part->children_count == 2);
+       test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(part->header_size.lines == 2);
+       test_assert(part->header_size.physical_size == 45);
+       test_assert(part->header_size.virtual_size == 45+2);
+       test_assert(part->body_size.lines == 21);
+       test_assert(part->body_size.physical_size == 238);
+       test_assert(part->body_size.virtual_size == 238+21);
+
+       part = parts->children;
+       test_assert(part->children_count == 1);
+       test_assert(part->flags == (MESSAGE_PART_FLAG_MULTIPART | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(part->header_size.lines == 2);
+       test_assert(part->header_size.physical_size == 45);
+       test_assert(part->header_size.virtual_size == 45+2);
+       test_assert(part->body_size.lines == 18);
+       test_assert(part->body_size.physical_size == 189);
+       test_assert(part->body_size.virtual_size == 189+18);
+
+       part = parts->children->children;
+       test_assert(part->children_count == 0);
+       test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME);
+       test_assert(part->header_size.lines == 2);
+       test_assert(part->header_size.physical_size == 30);
+       test_assert(part->header_size.virtual_size == 30+2);
+       test_assert(part->body_size.lines == 15);
+       test_assert(part->body_size.physical_size == 155);
+       test_assert(part->body_size.virtual_size == 155+15);
+
+       test_parsed_parts(input, parts);
+       i_stream_unref(&input);
+       pool_unref(&pool);
+       test_end();
+}
+
 static void test_message_parser_mime_version(void)
 {
        test_begin("message parser mime version");
@@ -1301,6 +1382,7 @@ int main(void)
                test_message_parser_mime_part_nested_limit,
                test_message_parser_mime_part_nested_limit_rfc822,
                test_message_parser_mime_part_limit,
+               test_message_parser_mime_part_limit_rfc822,
                test_message_parser_mime_version,
                test_message_parser_mime_version_missing,
                NULL