From a14b731f3c87df76a0b5112a19e9b36162491049 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 25 Jul 2018 13:17:45 +0300 Subject: [PATCH] lib-storage: Fix bodystructure parsing crash if header is parsed twice The second parsing will recreate the parser_ctx, discarding the old parsed message_part.data for the header. On the second parsing save_bodystructure_header=FALSE so the message_part.data isn't filled for the header. Later on the bodystructure parsing assumes the data is set, and crashes. This only happened with mail_attachment_detection_options=add-flags-on-save and Sieve script that first accessed a non-cached header and then used the "body" extension. Fixes segfault and also: Panic: file imap-bodystructure.c: line 116 (part_write_body_multipart): assertion failed: (part->data != NULL) --- src/lib-storage/index/index-mail-headers.c | 8 +++++++- src/lib-storage/index/index-mail.c | 5 +++-- src/lib-storage/index/index-mail.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index d5988dcd92..e51aa43ad3 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -313,7 +313,7 @@ void index_mail_parse_header(struct message_part *part, if (data->save_bodystructure_header) { i_assert(!data->save_bodystructure_body || data->parser_ctx != NULL); - data->save_bodystructure_header = FALSE; + data->parsed_bodystructure_header = TRUE; } return; } @@ -414,6 +414,12 @@ static void index_mail_init_parser(struct index_mail *mail) index_mail_set_message_parts_corrupted(&mail->mail.mail, error); data->parts = NULL; } + if (data->parts == NULL) { + /* The previous parsing didn't finish, so we're + re-parsing the header. The new parts don't have data + filled anymore. */ + data->parsed_bodystructure_header = FALSE; + } } if (data->parts == NULL) { diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 23c09ce823..07b4dd0fdd 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -1193,7 +1193,7 @@ static int index_mail_parse_body(struct index_mail *mail, if (data->save_bodystructure_body) { /* bodystructure header is parsed, we want the body's mime headers too */ - i_assert(!data->save_bodystructure_header); + i_assert(data->parsed_bodystructure_header); message_parser_parse_body(data->parser_ctx, parse_bodystructure_part_header, mail->mail.data_pool); @@ -1346,7 +1346,8 @@ static int index_mail_parse_bodystructure(struct index_mail *mail, a string */ index_mail_body_parsed_cache_bodystructure(mail, field); } else { - if (data->save_bodystructure_header || + if ((data->save_bodystructure_header && + !data->parsed_bodystructure_header) || !data->save_bodystructure_body || field == MAIL_CACHE_BODY_SNIPPET) { /* we haven't parsed the header yet */ diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index 8053704df2..6ba64057b5 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -118,6 +118,7 @@ struct index_mail_data { bool save_body_snippet:1; bool stream_has_only_header:1; bool parsed_bodystructure:1; + bool parsed_bodystructure_header:1; bool hdr_size_set:1; bool body_size_set:1; bool messageparts_saved_to_cache:1;