]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: Add MESSAGE_PART_FLAG_OVERFLOW to MIME parts that reached parsing limits
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 25 May 2021 17:03:53 +0000 (20:03 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 1 Jun 2021 18:17:43 +0000 (18:17 +0000)
This allows callers to find out which MIME parts were properly parsed.

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

index 6e45fe2caf524bdb1b3cfdb6968744aaa066d99e..9a9c9a3515f70a30c075f70cc2472f3133a175c0 100644 (file)
@@ -253,6 +253,7 @@ boundary_line_find(struct message_parser_ctx *ctx,
        if (ctx->total_parts_count >= ctx->max_total_mime_parts) {
                /* can't add any more MIME parts. just stop trying to find
                   more boundaries. */
+               ctx->part->flags |= MESSAGE_PART_FLAG_OVERFLOW;
                return -1;
        }
 
@@ -597,6 +598,7 @@ static int parse_next_header(struct message_parser_ctx *ctx,
                        parse_next_body_multipart_init(ctx);
                        ctx->multipart = TRUE;
                } else {
+                       part->flags |= MESSAGE_PART_FLAG_OVERFLOW;
                        part->flags &= ENUM_NEGATE(MESSAGE_PART_FLAG_MULTIPART);
                }
        }
@@ -702,11 +704,19 @@ static int parse_next_header(struct message_parser_ctx *ctx,
                i_assert(ctx->last_boundary == NULL);
                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) &&
+       } else if ((part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) == 0) {
+               /* Not message/rfc822 */
+               if (ctx->boundaries != NULL)
+                       ctx->parse_next_block = parse_next_body_to_boundary;
+               else
+                       ctx->parse_next_block = parse_next_body_to_eof;
+       } else if (!parse_too_many_nested_mime_parts(ctx) &&
                   ctx->total_parts_count < ctx->max_total_mime_parts) {
+               /* message/rfc822 - not reached MIME part limits yet */
                ctx->parse_next_block = parse_next_body_message_rfc822_init;
        } else {
+               /* message/rfc822 - already reached MIME part limits */
+               part->flags |= MESSAGE_PART_FLAG_OVERFLOW;
                part->flags &= ENUM_NEGATE(MESSAGE_PART_FLAG_MESSAGE_RFC822);
                if (ctx->boundaries != NULL)
                        ctx->parse_next_block = parse_next_body_to_boundary;
index 7f6afa374898a6dbd8ea00222c16adba403aaf9a..d8f99ab5d7b13bc51606b5642ff64d59a33fbb41 100644 (file)
@@ -21,7 +21,11 @@ enum message_part_flags {
        MESSAGE_PART_FLAG_HAS_NULS              = 0x20,
 
        /* Mime-Version header exists. */
-       MESSAGE_PART_FLAG_IS_MIME               = 0x40
+       MESSAGE_PART_FLAG_IS_MIME               = 0x40,
+       /* Message parsing was aborted because there were too many MIME parts.
+          This MIME part points to a blob which wasn't actually parsed to
+          see if it would contain further MIME parts. */
+       MESSAGE_PART_FLAG_OVERFLOW              = 0x80,
 };
 
 struct message_part {
index c4e117afc79d1cb0b401b9d5525181a479a40876..663bfe8c5a49cc2dd178e560ac8fe45e8aa93759 100644 (file)
@@ -965,7 +965,8 @@ static const char input_msg[] =
 
        part = parts->children;
        test_assert(part->children_count == 0);
-       test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME);
+       test_assert(part->flags == (MESSAGE_PART_FLAG_IS_MIME |
+                                   MESSAGE_PART_FLAG_OVERFLOW));
        test_assert(part->header_size.lines == 2);
        test_assert(part->header_size.physical_size == 45);
        test_assert(part->header_size.virtual_size == 45+2);
@@ -1029,7 +1030,8 @@ static const char input_msg[] =
 
        part = parts->children;
        test_assert(part->children_count == 0);
-       test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME);
+       test_assert(part->flags == (MESSAGE_PART_FLAG_IS_MIME |
+                                   MESSAGE_PART_FLAG_OVERFLOW));
        test_assert(part->header_size.lines == 2);
        test_assert(part->header_size.physical_size == 30);
        test_assert(part->header_size.virtual_size == 30+2);
@@ -1113,7 +1115,9 @@ static const char input_msg[] =
 
        part = parts->children->children->next;
        test_assert(part->children_count == 0);
-       test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_IS_MIME));
+       test_assert(part->flags == (MESSAGE_PART_FLAG_TEXT |
+                                   MESSAGE_PART_FLAG_IS_MIME |
+                                   MESSAGE_PART_FLAG_OVERFLOW));
        test_assert(part->header_size.lines == 2);
        test_assert(part->header_size.physical_size == 26);
        test_assert(part->header_size.virtual_size == 26+2);
@@ -1194,7 +1198,8 @@ static const char input_msg[] =
 
        part = parts->children->children;
        test_assert(part->children_count == 0);
-       test_assert(part->flags == MESSAGE_PART_FLAG_IS_MIME);
+       test_assert(part->flags == (MESSAGE_PART_FLAG_IS_MIME |
+                                   MESSAGE_PART_FLAG_OVERFLOW));
        test_assert(part->header_size.lines == 2);
        test_assert(part->header_size.physical_size == 30);
        test_assert(part->header_size.virtual_size == 30+2);
@@ -1277,7 +1282,9 @@ static const char *const input_msgs[] = {
                part = part->children;
 
                test_assert_idx(part->children_count == 0, i);
-               test_assert_idx(part->flags == 72, i);
+               test_assert_idx(part->flags == (MESSAGE_PART_FLAG_TEXT |
+                                               MESSAGE_PART_FLAG_IS_MIME |
+                                               MESSAGE_PART_FLAG_OVERFLOW), i);
                test_assert_idx(part->header_size.lines == 2, i);
                test_assert_idx(part->header_size.physical_size == 26, i);
                test_assert_idx(part->header_size.virtual_size == 28, i);