From fb97a1cddbda4019e327fa736972a1c7433fedaa Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 11 Sep 2020 09:53:03 +0300 Subject: [PATCH] lib-mail: message-parser - Fix assert-crash when enforcing MIME part limit The limit could have been exceeded with message/rfc822 parts. --- src/lib-mail/message-parser.c | 3 +- src/lib-mail/test-message-parser.c | 82 ++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/lib-mail/message-parser.c b/src/lib-mail/message-parser.c index 6ab4c3266f..40a504da0a 100644 --- a/src/lib-mail/message-parser.c +++ b/src/lib-mail/message-parser.c @@ -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 &= ~MESSAGE_PART_FLAG_MESSAGE_RFC822; diff --git a/src/lib-mail/test-message-parser.c b/src/lib-mail/test-message-parser.c index 8c5a3404f1..c4e117afc7 100644 --- a/src/lib-mail/test-message-parser.c +++ b/src/lib-mail/test-message-parser.c @@ -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(); +} + int main(void) { static void (*const test_functions[])(void) = { @@ -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, NULL }; return test_run(test_functions);