From: Timo Sirainen Date: Wed, 14 Dec 2011 11:00:05 +0000 (+0200) Subject: imapc: Avoid assert-crashing when replacing mail stream with a new one. X-Git-Tag: 2.1.rc2~40 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ed248fba21fdd3abcc4bb4d07c2822b9ba3f66f;p=thirdparty%2Fdovecot%2Fcore.git imapc: Avoid assert-crashing when replacing mail stream with a new one. --- diff --git a/src/lib-storage/index/imapc/imapc-mail-fetch.c b/src/lib-storage/index/imapc/imapc-mail-fetch.c index 1d2ff1c1cd..3d8c668450 100644 --- a/src/lib-storage/index/imapc/imapc-mail-fetch.c +++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c @@ -277,13 +277,13 @@ void imapc_mail_init_stream(struct imapc_mail *mail, bool have_body) if (imail->mail.v.istream_opened != NULL) { if (imail->mail.v.istream_opened(_mail, &imail->data.stream) < 0) { - i_stream_unref(&imail->data.stream); + index_mail_close_streams(imail); return; } } else if (have_body) { ret = i_stream_get_size(imail->data.stream, TRUE, &size); if (ret < 0) { - i_stream_unref(&imail->data.stream); + index_mail_close_streams(imail); return; } i_assert(ret != 0); @@ -295,7 +295,7 @@ void imapc_mail_init_stream(struct imapc_mail *mail, bool have_body) imail->data.stream_has_only_header = !have_body; if (index_mail_init_stream(imail, NULL, NULL, &input) < 0) - i_stream_unref(&imail->data.stream); + index_mail_close_streams(imail); } static void @@ -311,7 +311,7 @@ imapc_fetch_stream(struct imapc_mail *mail, if (!body) return; /* maybe the existing stream has no body. replace it. */ - i_stream_unref(&imail->data.stream); + index_mail_close_streams(imail); if (mail->fd != -1) { if (close(mail->fd) < 0) i_error("close(imapc mail) failed: %m"); diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 4d0c670348..85aef6f049 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -1137,7 +1137,7 @@ void index_mail_init(struct index_mail *mail, } } -void index_mail_close_streams(struct index_mail *mail) +static void index_mail_close_streams_full(struct index_mail *mail, bool closing) { struct index_mail_data *data = &mail->data; struct message_part *parts; @@ -1152,14 +1152,31 @@ void index_mail_close_streams(struct index_mail *mail) i_stream_unref(&data->filter_stream); if (data->stream != NULL) { data->destroying_stream = TRUE; + if (!closing) { + /* we're replacing the stream with a new one. it's + allowed to have references until the mail is closed + (but we can't really check that) */ + i_stream_unset_destroy_callback(data->stream); + } i_stream_unref(&data->stream); - i_assert(!data->destroying_stream); + if (closing) { + /* there must be no references to the mail when the + mail is being closed. */ + i_assert(!mail->data.destroying_stream); + } else { + data->destroying_stream = FALSE; + } data->initialized_wrapper_stream = FALSE; data->destroy_callback_set = FALSE; } } +void index_mail_close_streams(struct index_mail *mail) +{ + index_mail_close_streams_full(mail, FALSE); +} + void index_mail_close(struct mail *_mail) { struct index_mail *mail = (struct index_mail *)_mail; @@ -1174,7 +1191,8 @@ void index_mail_close(struct mail *_mail) index_mail_cache_dates(mail); } - index_mail_close_streams(mail); + index_mail_close_streams_full(mail, TRUE); + if (mail->data.wanted_headers != NULL) mailbox_header_lookup_unref(&mail->data.wanted_headers); }