]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Reset bodystructure parsing state when reseting message_parts
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 25 Oct 2021 09:22:06 +0000 (12:22 +0300)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Mon, 21 Feb 2022 16:21:23 +0000 (16:21 +0000)
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/index/index-mail.c
src/lib-storage/index/index-mail.h
src/lib-storage/test-mail.c

index d9603628e5e99cc672f59fd0ca467ff79e15a421..ce23e9df04ab5e0992992fb6c27fae10168bd211 100644 (file)
@@ -423,7 +423,7 @@ static void index_mail_init_parser(struct index_mail *mail)
                data->parser_input = NULL;
                if (message_parser_deinit_from_parts(&data->parser_ctx, &parts, &error) < 0) {
                        index_mail_set_message_parts_corrupted(&mail->mail.mail, error);
-                       data->parts = NULL;
+                       index_mail_parts_reset(mail);
                }
                if (data->parts == NULL || data->parts != parts) {
                        /* The previous parsing didn't finish, so we're
index 87b9efc1563529f34e75f7ae2e147f0b4beb5e53..7e0b6f81ac54cf55f02eccebb3ca51427a2db125 100644 (file)
@@ -1142,6 +1142,13 @@ static int index_mail_write_body_snippet(struct index_mail *mail)
        return ret;
 }
 
+void index_mail_parts_reset(struct index_mail *mail)
+{
+       mail->data.parts = NULL;
+       mail->data.parsed_bodystructure_header = FALSE;
+       mail->data.parsed_bodystructure = FALSE;
+}
+
 static int
 index_mail_parse_body_finish(struct index_mail *mail,
                             enum index_cache_field field, bool success)
@@ -1191,8 +1198,7 @@ index_mail_parse_body_finish(struct index_mail *mail,
                        i_assert(error != NULL);
                        index_mail_set_message_parts_corrupted(&mail->mail.mail, error);
                }
-               mail->data.parts = NULL;
-               mail->data.parsed_bodystructure = FALSE;
+               index_mail_parts_reset(mail);
                if (mail->data.save_bodystructure_body)
                        mail->data.save_bodystructure_header = TRUE;
                if (mail->data.header_parser_initialized)
@@ -2524,19 +2530,19 @@ void index_mail_set_cache_corrupted(struct mail *mail,
                field_name = "physical size";
                imail->data.physical_size = UOFF_T_MAX;
                imail->data.virtual_size = UOFF_T_MAX;
-               imail->data.parts = NULL;
+               index_mail_parts_reset(imail);
                index_mail_reset_vsize_ext(mail);
                break;
        case MAIL_FETCH_VIRTUAL_SIZE:
                field_name = "virtual size";
                imail->data.physical_size = UOFF_T_MAX;
                imail->data.virtual_size = UOFF_T_MAX;
-               imail->data.parts = NULL;
+               index_mail_parts_reset(imail);
                index_mail_reset_vsize_ext(mail);
                break;
        case MAIL_FETCH_MESSAGE_PARTS:
                field_name = "MIME parts";
-               imail->data.parts = NULL;
+               index_mail_parts_reset(imail);
                break;
        case MAIL_FETCH_IMAP_BODY:
                field_name = "IMAP BODY";
index afd240413145d673514dc0b1f4b85245e99768b7..74107d277d26a2386df19c183e1399596cb527a2 100644 (file)
@@ -205,6 +205,7 @@ int index_mail_parse_headers_internal(struct index_mail *mail,
                                      struct mailbox_header_lookup_ctx *headers)
        ATTR_NULL(2);
 int index_mail_headers_get_envelope(struct index_mail *mail);
+void index_mail_parts_reset(struct index_mail *mail);
 
 int index_mail_get_first_header(struct mail *_mail, const char *field,
                                bool decode_to_utf8, const char **value_r);
index b39b1d01f1532316865339006f4b380de14cba1a..d68fda76bdded963f9cc31e67d26d7e3801fbd56 100644 (file)
@@ -437,12 +437,53 @@ static void test_bodystructure_reparsing(void)
        test_end();
 }
 
+static void test_bodystructure_corruption_reparsing(void)
+{
+       struct test_mail_storage_ctx *ctx;
+       struct test_mail_storage_settings set = {
+               .driver = "sdbox",
+       };
+       const char *value;
+
+       test_begin("bodystructure corruption 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, 0, NULL);
+       mail_set_seq(mail, 1);
+
+       test_assert(mail_get_special(mail, MAIL_FETCH_IMAP_BODY, &value) == 0);
+       test_expect_error_string("Mailbox INBOX: Deleting corrupted cache record uid=1: UID 1: Broken MIME parts in mailbox INBOX: test");
+       mail_set_cache_corrupted(mail, MAIL_FETCH_MESSAGE_PARTS, "test");
+       test_expect_no_more_errors();
+       test_assert(mail_get_special(mail, MAIL_FETCH_IMAP_BODYSTRUCTURE, &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,
+               test_bodystructure_corruption_reparsing,
                NULL
        };
        int ret;