Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
lib-mail: message_parser_init_from_parts() - Fix crash if MIME bounda…
…ries don't end

If the last "boundary--" doens't exist, the parsing assert-crashed at
deinit. This mainly happened when searching mails.

Fixes:
Panic: file message-parser.c: line 175 (message_part_finish): assertion failed: (ctx->nested_parts_count > 0)
  • Loading branch information
sirainen committed Sep 23, 2020
1 parent 86e1953 commit a668d76
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 6 deletions.
13 changes: 8 additions & 5 deletions src/lib-mail/message-parser.c
Expand Up @@ -138,6 +138,7 @@ message_part_append(struct message_parser_ctx *ctx)
struct message_part *parent = ctx->part;
struct message_part *part;

i_assert(!ctx->preparsed);
i_assert(parent != NULL);
i_assert((parent->flags & (MESSAGE_PART_FLAG_MULTIPART |
MESSAGE_PART_FLAG_MESSAGE_RFC822)) != 0);
Expand Down Expand Up @@ -171,12 +172,14 @@ static void message_part_finish(struct message_parser_ctx *ctx)
{
struct message_part **const *parent_next_partp;

i_assert(ctx->nested_parts_count > 0);
ctx->nested_parts_count--;
if (!ctx->preparsed) {
i_assert(ctx->nested_parts_count > 0);
ctx->nested_parts_count--;

parent_next_partp = array_back(&ctx->next_part_stack);
array_pop_back(&ctx->next_part_stack);
ctx->next_part = *parent_next_partp;
parent_next_partp = array_back(&ctx->next_part_stack);
array_pop_back(&ctx->next_part_stack);
ctx->next_part = *parent_next_partp;
}

message_size_add(&ctx->part->parent->body_size, &ctx->part->body_size);
message_size_add(&ctx->part->parent->body_size, &ctx->part->header_size);
Expand Down
21 changes: 20 additions & 1 deletion src/lib-mail/test-message-parser.c
Expand Up @@ -178,9 +178,10 @@ static void test_message_parser_small_blocks(void)
static void test_message_parser_stop_early(void)
{
struct message_parser_ctx *parser;
struct istream *input;
struct istream *input, *input2;
struct message_part *parts;
struct message_block block;
const char *error;
unsigned int i;
pool_t pool;
int ret;
Expand All @@ -198,6 +199,24 @@ static void test_message_parser_stop_early(void)
&block)) > 0) ;
test_assert(ret == 0);
message_parser_deinit(&parser, &parts);

/* test preparsed - first re-parse everything with a stream
that sees EOF at this position */
input2 = i_stream_create_from_data(test_msg, i);
parser = message_parser_init(pool, input2, &set_empty);
while ((ret = message_parser_parse_next_block(parser,
&block)) > 0) ;
test_assert(ret == -1);
message_parser_deinit(&parser, &parts);

/* now parse from the parts */
i_stream_seek(input2, 0);
parser = message_parser_init_from_parts(parts, input2, &set_empty);
while ((ret = message_parser_parse_next_block(parser,
&block)) > 0) ;
test_assert(ret == -1);
test_assert(message_parser_deinit_from_parts(&parser, &parts, &error) == 0);
i_stream_unref(&input2);
}

i_stream_unref(&input);
Expand Down

0 comments on commit a668d76

Please sign in to comment.