dovecot-1.2: Message parsing/reading: If read returns failure, d...

dovecot at dovecot.org dovecot at dovecot.org
Sat Dec 13 09:38:58 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/c63cc3580150
changeset: 8526:c63cc3580150
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Dec 13 08:36:59 2008 +0200
description:
Message parsing/reading: If read returns failure, don't ignore the error.

diffstat:

7 files changed, 84 insertions(+), 38 deletions(-)
src/imap/imap-fetch-body.c           |   55 ++++++++++++++++++++++++----------
src/lib-mail/istream-header-filter.c |   15 +++++++--
src/lib-mail/message-send.c          |   13 ++++----
src/lib-mail/message-send.h          |    6 +--
src/lib-mail/message-size.c          |   21 +++++++++---
src/lib-mail/message-size.h          |    8 ++--
src/lib-storage/index/index-mail.c   |    4 +-

diffs (294 lines):

diff -r 9c8b0f8075d2 -r c63cc3580150 src/imap/imap-fetch-body.c
--- a/src/imap/imap-fetch-body.c	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/imap/imap-fetch-body.c	Sat Dec 13 08:36:59 2008 +0200
@@ -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)
-{
-	bool cr_skipped;
-
+static void fetch_read_error(struct imap_fetch_context *ctx)
+{
+	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 se
 
 	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
 			}
 		}
 	}
+	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_
 		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(str
 	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_fet
 	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 -r 9c8b0f8075d2 -r c63cc3580150 src/lib-mail/istream-header-filter.c
--- a/src/lib-mail/istream-header-filter.c	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-mail/istream-header-filter.c	Sat Dec 13 08:36:59 2008 +0200
@@ -234,9 +234,18 @@ static ssize_t read_header(struct header
 		}
 	}
 
-	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 -r 9c8b0f8075d2 -r c63cc3580150 src/lib-mail/message-send.c
--- a/src/lib-mail/message-send.c	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-mail/message-send.c	Sat Dec 13 08:36:59 2008 +0200
@@ -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
 
 		cr_skipped = msg[i-1] == '\r';
 	}
+	i_assert(ret == -1);
+	return input->stream_errno == 0 ? 0 : -1;
 }
diff -r 9c8b0f8075d2 -r c63cc3580150 src/lib-mail/message-send.h
--- a/src/lib-mail/message-send.h	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-mail/message-send.h	Sat Dec 13 08:36:59 2008 +0200
@@ -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 -r 9c8b0f8075d2 -r c63cc3580150 src/lib-mail/message-size.c
--- a/src/lib-mail/message-size.c	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-mail/message-size.c	Sat Dec 13 08:36:59 2008 +0200
@@ -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 istr
 
 		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 istrea
 		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 -r 9c8b0f8075d2 -r c63cc3580150 src/lib-mail/message-size.h
--- a/src/lib-mail/message-size.h	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-mail/message-size.h	Sat Dec 13 08:36:59 2008 +0200
@@ -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 -r 9c8b0f8075d2 -r c63cc3580150 src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c	Sat Dec 13 08:36:16 2008 +0200
+++ b/src/lib-storage/index/index-mail.c	Sat Dec 13 08:36:59 2008 +0200
@@ -795,6 +795,7 @@ int index_mail_init_stream(struct index_
 			   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_
 		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,


More information about the dovecot-cvs mailing list