# HG changeset patch # User Timo Sirainen # Date 1532513865 -10800 # Node ID 4e9251b0435d74e3cfec9936202dc700c6742f8c # Parent c3c55b15fb6f8160c7e10c5e93f64958bebc49d5 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) diff -r c3c55b15fb6f -r 4e9251b0435d src/lib-storage/index/index-mail-headers.c --- a/src/lib-storage/index/index-mail-headers.c Wed Jul 25 13:17:05 2018 +0300 +++ b/src/lib-storage/index/index-mail-headers.c Wed Jul 25 13:17:45 2018 +0300 @@ -315,7 +315,7 @@ 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; } @@ -416,6 +416,12 @@ 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 -r c3c55b15fb6f -r 4e9251b0435d src/lib-storage/index/index-mail.c --- a/src/lib-storage/index/index-mail.c Wed Jul 25 13:17:05 2018 +0300 +++ b/src/lib-storage/index/index-mail.c Wed Jul 25 13:17:45 2018 +0300 @@ -1182,7 +1182,7 @@ 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); @@ -1327,7 +1327,8 @@ 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 -r c3c55b15fb6f -r 4e9251b0435d src/lib-storage/index/index-mail.h --- a/src/lib-storage/index/index-mail.h Wed Jul 25 13:17:05 2018 +0300 +++ b/src/lib-storage/index/index-mail.h Wed Jul 25 13:17:45 2018 +0300 @@ -118,6 +118,7 @@ unsigned int save_body_snippet:1; unsigned int stream_has_only_header:1; unsigned int parsed_bodystructure:1; + unsigned int parsed_bodystructure_header:1; unsigned int hdr_size_set:1; unsigned int body_size_set:1; unsigned int messageparts_saved_to_cache:1;