From: Timo Sirainen Date: Sat, 13 Dec 2008 06:36:59 +0000 (+0200) Subject: Message parsing/reading: If read returns failure, don't ignore the error. X-Git-Tag: 1.2.alpha5~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3b5028747f195bca08751015e5b5a28cd5f4f8d4;p=thirdparty%2Fdovecot%2Fcore.git Message parsing/reading: If read returns failure, don't ignore the error. --HG-- branch : HEAD --- diff --git a/src/imap/imap-fetch-body.c b/src/imap/imap-fetch-body.c index 5382613872..bfc3402e0c 100644 --- a/src/imap/imap-fetch-body.c +++ b/src/imap/imap-fetch-body.c @@ -43,12 +43,18 @@ struct partial_cache { static struct partial_cache last_partial = { 0, 0, 0, 0, { 0, 0, 0 } }; -static bool seek_partial(unsigned int select_counter, unsigned int uid, - struct partial_cache *partial, struct istream *stream, - uoff_t virtual_skip) +static void fetch_read_error(struct imap_fetch_context *ctx) { - bool cr_skipped; + errno = ctx->cur_input->stream_errno; + i_error("FETCH for mailbox %s UID %u " + "failed to read message input: %m", + mailbox_get_name(ctx->mail->box), ctx->mail->uid); +} +static int seek_partial(unsigned int select_counter, unsigned int uid, + struct partial_cache *partial, struct istream *stream, + uoff_t virtual_skip, bool *cr_skipped_r) +{ if (select_counter == partial->select_counter && uid == partial->uid && stream->v_offset == partial->physical_start && virtual_skip >= partial->pos.virtual_size) { @@ -64,11 +70,12 @@ static bool seek_partial(unsigned int select_counter, unsigned int uid, i_stream_seek(stream, partial->physical_start + partial->pos.physical_size); - message_skip_virtual(stream, virtual_skip, &partial->pos, - partial->cr_skipped, &cr_skipped); + if (message_skip_virtual(stream, virtual_skip, &partial->pos, + partial->cr_skipped, cr_skipped_r) < 0) + return -1; partial->cr_skipped = FALSE; - return cr_skipped; + return 0; } static uoff_t get_send_size(const struct imap_fetch_body_data *body, @@ -174,6 +181,10 @@ static off_t imap_fetch_send(struct imap_fetch_context *ctx, } } } + if (input->stream_errno != 0) { + fetch_read_error(ctx); + return -1; + } if (add_missing_eoh && sent + 2 == virtual_size) { /* Netscape missing EOH workaround. */ @@ -307,12 +318,18 @@ static int fetch_data(struct imap_fetch_context *ctx, return -1; if (!ctx->update_partial) { - message_skip_virtual(ctx->cur_input, body->skip, NULL, FALSE, - &ctx->skip_cr); + if (message_skip_virtual(ctx->cur_input, body->skip, NULL, + FALSE, &ctx->skip_cr) < 0) { + fetch_read_error(ctx); + return -1; + } } else { - ctx->skip_cr = - seek_partial(ctx->select_counter, ctx->cur_mail->uid, - &last_partial, ctx->cur_input, body->skip); + if (seek_partial(ctx->select_counter, ctx->cur_mail->uid, + &last_partial, ctx->cur_input, body->skip, + &ctx->skip_cr) < 0) { + fetch_read_error(ctx); + return -1; + } } return fetch_stream(ctx, size); @@ -407,7 +424,10 @@ static int fetch_header_partial_from(struct imap_fetch_context *ctx, ctx->update_partial = FALSE; old_offset = ctx->cur_input->v_offset; - message_get_header_size(ctx->cur_input, &msg_size, NULL); + if (message_get_header_size(ctx->cur_input, &msg_size, NULL) < 0) { + fetch_read_error(ctx); + return -1; + } i_stream_seek(ctx->cur_input, old_offset); if (!ctx->cur_have_eoh && @@ -455,7 +475,10 @@ fetch_body_header_fields(struct imap_fetch_context *ctx, struct mail *mail, ctx->update_partial = FALSE; old_offset = ctx->cur_input->v_offset; - message_get_body_size(ctx->cur_input, &size, NULL); + if (message_get_body_size(ctx->cur_input, &size, NULL) < 0) { + fetch_read_error(ctx); + return -1; + } i_stream_seek(ctx->cur_input, old_offset); /* FIXME: We'll just always add the end of headers line now. diff --git a/src/lib-mail/istream-header-filter.c b/src/lib-mail/istream-header-filter.c index db72583891..156f3ca0d7 100644 --- a/src/lib-mail/istream-header-filter.c +++ b/src/lib-mail/istream-header-filter.c @@ -234,9 +234,18 @@ static ssize_t read_header(struct header_filter_istream *mstream) } } - if (hdr_ret < 0 && !mstream->seen_eoh && mstream->add_missing_eoh) { - mstream->seen_eoh = TRUE; - add_eol(mstream); + if (hdr_ret < 0) { + if (mstream->istream.parent->stream_errno != 0) { + mstream->istream.istream.stream_errno = + mstream->istream.parent->stream_errno; + mstream->istream.istream.eof = + mstream->istream.parent->eof; + return -1; + } + if (!mstream->seen_eoh && mstream->add_missing_eoh) { + mstream->seen_eoh = TRUE; + add_eol(mstream); + } } /* don't copy eof here because we're only returning headers here. diff --git a/src/lib-mail/message-send.c b/src/lib-mail/message-send.c index 99806449f7..66d2779866 100644 --- a/src/lib-mail/message-send.c +++ b/src/lib-mail/message-send.c @@ -7,21 +7,22 @@ #include "message-send.h" #include "message-size.h" -void message_skip_virtual(struct istream *input, uoff_t virtual_skip, - struct message_size *msg_size, - bool cr_skipped, bool *last_cr) +int message_skip_virtual(struct istream *input, uoff_t virtual_skip, + struct message_size *msg_size, + bool cr_skipped, bool *last_cr) { const unsigned char *msg; size_t i, size, startpos; + int ret; if (virtual_skip == 0) { *last_cr = cr_skipped; - return; + return 0; } *last_cr = FALSE; startpos = 0; - while (i_stream_read_data(input, &msg, &size, startpos) > 0) { + while ((ret = i_stream_read_data(input, &msg, &size, startpos)) > 0) { for (i = startpos; i < size && virtual_skip > 0; i++) { virtual_skip--; @@ -64,4 +65,6 @@ void message_skip_virtual(struct istream *input, uoff_t virtual_skip, cr_skipped = msg[i-1] == '\r'; } + i_assert(ret == -1); + return input->stream_errno == 0 ? 0 : -1; } diff --git a/src/lib-mail/message-send.h b/src/lib-mail/message-send.h index f10ec2840c..c0c2373b55 100644 --- a/src/lib-mail/message-send.h +++ b/src/lib-mail/message-send.h @@ -7,8 +7,8 @@ struct message_size; NULL. If cr_skipped is TRUE and first character is \n, it's not treated as \r\n. last_cr is set to TRUE if last character we skipped was \r, meaning that next character should be \n and you shouldn't treat it as \r\n. */ -void message_skip_virtual(struct istream *input, uoff_t virtual_skip, - struct message_size *msg_size, - bool cr_skipped, bool *last_cr); +int message_skip_virtual(struct istream *input, uoff_t virtual_skip, + struct message_size *msg_size, + bool cr_skipped, bool *last_cr); #endif diff --git a/src/lib-mail/message-size.c b/src/lib-mail/message-size.c index b8545b2380..f96b4830ab 100644 --- a/src/lib-mail/message-size.c +++ b/src/lib-mail/message-size.c @@ -5,11 +5,12 @@ #include "message-parser.h" #include "message-size.h" -void message_get_header_size(struct istream *input, struct message_size *hdr, - bool *has_nuls) +int message_get_header_size(struct istream *input, struct message_size *hdr, + bool *has_nuls) { const unsigned char *msg; size_t i, size, startpos, missing_cr_count; + int ret = 0; memset(hdr, 0, sizeof(struct message_size)); if (has_nuls != NULL) @@ -54,27 +55,31 @@ void message_get_header_size(struct istream *input, struct message_size *hdr, hdr->physical_size += i - startpos; } + if (input->stream_errno != 0) + ret = -1; i_stream_skip(input, startpos); hdr->physical_size += startpos; hdr->virtual_size = hdr->physical_size + missing_cr_count; i_assert(hdr->virtual_size >= hdr->physical_size); + return ret; } -void message_get_body_size(struct istream *input, struct message_size *body, - bool *has_nuls) +int message_get_body_size(struct istream *input, struct message_size *body, + bool *has_nuls) { const unsigned char *msg; size_t i, size, missing_cr_count; bool last_cr; + int ret = 0; memset(body, 0, sizeof(struct message_size)); if (has_nuls != NULL) *has_nuls = FALSE; missing_cr_count = 0; last_cr = FALSE; - if (i_stream_read_data(input, &msg, &size, 0) <= 0) - return; + if ((ret = i_stream_read_data(input, &msg, &size, 0)) <= 0) + return ret < 0 && input->stream_errno != 0 ? -1 : 0; if (msg[0] == '\n') missing_cr_count++; @@ -104,11 +109,15 @@ void message_get_body_size(struct istream *input, struct message_size *body, body->physical_size += i - 1; } while (i_stream_read_data(input, &msg, &size, 1) > 0); + if (input->stream_errno != 0) + ret = -1; + i_stream_skip(input, 1); body->physical_size++; body->virtual_size = body->physical_size + missing_cr_count; i_assert(body->virtual_size >= body->physical_size); + return ret; } void message_size_add(struct message_size *dest, diff --git a/src/lib-mail/message-size.h b/src/lib-mail/message-size.h index 1593de4a52..bdb3fd359f 100644 --- a/src/lib-mail/message-size.h +++ b/src/lib-mail/message-size.h @@ -9,11 +9,11 @@ struct message_size { /* Calculate size of message header. Leave the input point to first character in body. */ -void message_get_header_size(struct istream *input, struct message_size *hdr, - bool *has_nuls); +int message_get_header_size(struct istream *input, struct message_size *hdr, + bool *has_nuls); /* Calculate size of message body. */ -void message_get_body_size(struct istream *input, struct message_size *body, - bool *has_nuls); +int message_get_body_size(struct istream *input, struct message_size *body, + bool *has_nuls); /* Sum contents of src into dest. */ void message_size_add(struct message_size *dest, diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index c5435ae220..6e560ae070 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -795,6 +795,7 @@ int index_mail_init_stream(struct index_mail *mail, struct istream **stream_r) { struct index_mail_data *data = &mail->data; + int ret; i_stream_set_destroy_callback(data->stream, index_mail_stream_destroy_callback, mail); @@ -845,10 +846,11 @@ int index_mail_init_stream(struct index_mail *mail, data->physical_size = data->hdr_size.physical_size + data->body_size.physical_size; } + ret = index_mail_stream_check_failure(mail); i_stream_seek(data->stream, 0); *stream_r = data->stream; - return 0; + return ret; } static int index_mail_parse_bodystructure(struct index_mail *mail,