From: Timo Sirainen Date: Mon, 25 Oct 2021 09:22:06 +0000 (+0300) Subject: lib-storage: Reset bodystructure parsing state when reseting message_parts X-Git-Tag: 2.3.19~67 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6b6d61e9d1e940330aa87188bc2e365d2c3a5129;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Reset bodystructure parsing state when reseting message_parts Fixes: Panic: file message-part-data.c: line 28 (message_part_data_is_plain_7bit): assertion failed: (data != NULL) --- diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index d9603628e5..ce23e9df04 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -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 diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 87b9efc156..7e0b6f81ac 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -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"; diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index afd2404131..74107d277d 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -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); diff --git a/src/lib-storage/test-mail.c b/src/lib-storage/test-mail.c index b39b1d01f1..d68fda76bd 100644 --- a/src/lib-storage/test-mail.c +++ b/src/lib-storage/test-mail.c @@ -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: \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;