]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Message parsing/reading: If read returns failure, don't ignore the error.
authorTimo Sirainen <tss@iki.fi>
Sat, 13 Dec 2008 06:36:59 +0000 (08:36 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 13 Dec 2008 06:36:59 +0000 (08:36 +0200)
--HG--
branch : HEAD

src/imap/imap-fetch-body.c
src/lib-mail/istream-header-filter.c
src/lib-mail/message-send.c
src/lib-mail/message-send.h
src/lib-mail/message-size.c
src/lib-mail/message-size.h
src/lib-storage/index/index-mail.c

index 5382613872ced97bf0543abd95c3dc8cc534c1d5..bfc3402e0c10955fe0eccf7ac56fd5693d59333e 100644 (file)
@@ -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.
index db725838911d679ba90e2e1fc5b51fdcea54c8f5..156f3ca0d71930cd26b2744d21451ff59cfa54ed 100644 (file)
@@ -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.
index 99806449f7c35954dfb23e9c477a563b31f97799..66d2779866ee6b890a5ed413f6e09719b0ba3adc 100644 (file)
@@ -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;
 }
index f10ec2840cac0f1da1fc31d3ad115030f3f46027..c0c2373b5582ec2730adda739a67d10fa63a115d 100644 (file)
@@ -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
index b8545b23808ccc9996a438a9d609f6413a8e21ae..f96b4830ab5c465d96dd4d068f832be74b7a24c6 100644 (file)
@@ -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,
index 1593de4a522f0d1b54f003c372f110a75f465259..bdb3fd359fc801dc73d3f67d9569d3a34c56941e 100644 (file)
@@ -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,
index c5435ae220a7b107ccd51873ed0789ac35788b52..6e560ae07031d602f5f415b150ddfd8e49827bc6 100644 (file)
@@ -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,