]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix potential assert-crash when fetching body snippet
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 30 Nov 2020 20:10:28 +0000 (22:10 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Tue, 8 Dec 2020 09:17:16 +0000 (09:17 +0000)
This happened only in a rather special condition. Added unit test to
reproduce it.

Fixes:
Panic: file message-part-data.c: line 28 (message_part_data_is_plain_7bit): assertion failed: (data != NULL)

src/lib-storage/index/index-mail-headers.c
src/lib-storage/test-mail.c

index d67b96e8318c4b304493b7ee52f89066c1c4389d..d63c24fbbee8d56a059930af00544df144676782 100644 (file)
@@ -417,7 +417,7 @@ 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) {
+               if (data->parts == NULL || data->parts != parts) {
                        /* The previous parsing didn't finish, so we're
                           re-parsing the header. The new parts don't have data
                           filled anymore. */
index 8b799cece35fd22efeb8912f0500283413a183de..b39b1d01f1532316865339006f4b380de14cba1a 100644 (file)
@@ -393,11 +393,56 @@ static void test_attachment_flags_during_header_fetch(void)
        test_end();
 }
 
+static void test_bodystructure_reparsing(void)
+{
+       struct test_mail_storage_ctx *ctx;
+       struct test_mail_storage_settings set = {
+               .driver = "sdbox",
+               .extra_input = (const char *const[]) {
+                       "mail_attachment_detection_options=add-flags",
+                       "mail_never_cache_fields=flags",
+                       NULL
+               },
+       };
+       const char *value;
+
+       test_begin("mail bodystructure reparsing");
+       ctx = test_mail_storage_init();
+       test_mail_storage_init_user(ctx, &set);
+
+       struct mailbox *box =
+               mailbox_alloc(ctx->user->namespaces->list, "INBOX", 0);
+       test_assert(mailbox_open(box) == 0);
+
+       test_mail_save(box,
+                      "From: <test1@example.com>\r\n"
+                      "\r\n"
+                      "test body\n");
+
+       struct mailbox_transaction_context *trans =
+               mailbox_transaction_begin(box, 0, __func__);
+       struct mail *mail = mail_alloc(trans, MAIL_FETCH_IMAP_BODYSTRUCTURE, NULL);
+       mail_set_seq(mail, 1);
+
+       /* start parsing header */
+       test_assert(mail_get_first_header(mail, "From", &value) == 1);
+       /* fetching snippet triggers re-parsing the header */
+       test_assert(mail_get_special(mail, MAIL_FETCH_BODY_SNIPPET, &value) == 0);
+
+       mail_free(&mail);
+       test_assert(mailbox_transaction_commit(&trans) == 0);
+       mailbox_free(&box);
+       test_mail_storage_deinit_user(ctx);
+       test_mail_storage_deinit(&ctx);
+       test_end();
+}
+
 int main(int argc, char **argv)
 {
        void (*const tests[])(void) = {
                test_mail_random_access,
                test_attachment_flags_during_header_fetch,
+               test_bodystructure_reparsing,
                NULL
        };
        int ret;