]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix bodystructure parsing crash if header is parsed twice
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 25 Jul 2018 10:17:45 +0000 (13:17 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Fri, 25 Jan 2019 09:33:37 +0000 (11:33 +0200)
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
src/lib-storage/index/index-mail.c
src/lib-storage/index/index-mail.h

index 7e3753f3e6d2ee65bdc5da98459f1fdcbe01fe9a..f02bfe6423a9698f202085c75bc690fa2483866c 100644 (file)
@@ -315,7 +315,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;
        }
@@ -416,6 +416,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) {
index c520cfdf730dc8ec5dc5941adabe029d7820b300..46a6cb2113e3d79f1d5cc91d7cea893598a9da62 100644 (file)
@@ -1182,7 +1182,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);
@@ -1327,7 +1327,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 */
index 9dc652cdcfb9f99183c3f0a2d0ce86eb0bfcbf8b..c4994f031a0490bd4a84076894dd6bbd4792d976 100644 (file)
@@ -118,6 +118,7 @@ struct index_mail_data {
        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;