From: Timo Sirainen Date: Tue, 22 Jan 2013 14:31:17 +0000 (+0200) Subject: lib-storage: Catch input stream errors when parsing mail. X-Git-Tag: 2.1.14~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=49be238e250e99af8c69321264a461d8f6ceef62;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Catch input stream errors when parsing mail. --- diff --git a/src/lib-storage/index/index-mail-headers.c b/src/lib-storage/index/index-mail-headers.c index fb14c52a17..1e3b985101 100644 --- a/src/lib-storage/index/index-mail-headers.c +++ b/src/lib-storage/index/index-mail-headers.c @@ -374,6 +374,7 @@ index_mail_cache_parse_init(struct mail *_mail, struct istream *input) input2 = tee_i_stream_create_child(mail->data.tee_stream); index_mail_parse_header_init(mail, NULL); + mail->data.parser_input = input; mail->data.parser_ctx = message_parser_init(mail->data_pool, input, hdr_parser_flags, msg_parser_flags); @@ -386,10 +387,13 @@ static void index_mail_init_parser(struct index_mail *mail) struct index_mail_data *data = &mail->data; struct message_part *parts; - if (data->parser_ctx != NULL) + if (data->parser_ctx != NULL) { + data->parser_input = NULL; (void)message_parser_deinit(&data->parser_ctx, &parts); + } if (data->parts == NULL) { + data->parser_input = data->stream; data->parser_ctx = message_parser_init(mail->data_pool, data->stream, hdr_parser_flags, diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index cfc1480420..c014d6c5a9 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -751,13 +751,38 @@ static void index_mail_cache_dates(struct index_mail *mail) static int index_mail_parse_body_finish(struct index_mail *mail, enum index_cache_field field) { - if (message_parser_deinit(&mail->data.parser_ctx, - &mail->data.parts) < 0) { - mail_set_cache_corrupted(&mail->mail.mail, - MAIL_FETCH_MESSAGE_PARTS); + struct istream *parser_input = mail->data.parser_input; + int ret; + + if (parser_input == NULL) { + ret = message_parser_deinit(&mail->data.parser_ctx, + &mail->data.parts) < 0 ? 0 : 1; + } else { + mail->data.parser_input = NULL; + i_stream_ref(parser_input); + ret = message_parser_deinit(&mail->data.parser_ctx, + &mail->data.parts) < 0 ? 0 : 1; + if (parser_input->stream_errno != 0) { + errno = parser_input->stream_errno; + mail_storage_set_critical(mail->mail.mail.box->storage, + "read(%s) failed: %m", + i_stream_get_name(parser_input)); + ret = -1; + } + i_assert(i_stream_read(parser_input) == -1 && + !i_stream_have_bytes_left(parser_input)); + i_stream_unref(&parser_input); + } + if (ret <= 0) { + if (ret == 0) { + mail_set_cache_corrupted(&mail->mail.mail, + MAIL_FETCH_MESSAGE_PARTS); + } + mail->data.parts = NULL; mail->data.parsed_bodystructure = FALSE; return -1; } + if (mail->data.no_caching) { /* if we're here because we aborted parsing, don't get any further or we may crash while generating output from @@ -1150,6 +1175,7 @@ static void index_mail_close_streams_full(struct index_mail *mail, bool closing) mail_set_cache_corrupted(&mail->mail.mail, MAIL_FETCH_MESSAGE_PARTS); } + mail->data.parser_input = NULL; } if (data->filter_stream != NULL) i_stream_unref(&data->filter_stream); diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index 7210387d6d..45d8f4f7a3 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -96,6 +96,7 @@ struct index_mail_data { struct istream *stream, *filter_stream; struct tee_istream *tee_stream; struct message_size hdr_size, body_size; + struct istream *parser_input; struct message_parser_ctx *parser_ctx; int parsing_count; ARRAY_TYPE(keywords) keywords;