]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-mail: istream-attachment-extractor - Don't modify buffer during failure
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 26 Oct 2017 15:36:09 +0000 (18:36 +0300)
committerTimo Sirainen <tss@dovecot.fi>
Wed, 1 Nov 2017 11:45:51 +0000 (13:45 +0200)
If i_stream_read() returns -1 because the attachment file couldn't be
created, don't add the trailing data to the main istream. It's not useful,
and the following extra checks will cause it to assert-crash.

src/lib-mail/istream-attachment-extractor.c

index 3f59b7e6d09c4624002004d039eef64f6d5e31d1..8420548aeb1ef6d52075d2302bb7802ec161b33b 100644 (file)
@@ -336,10 +336,10 @@ static void astream_add_body(struct attachment_istream *astream,
        }
 }
 
-static int astream_decode_base64(struct attachment_istream *astream)
+static int astream_decode_base64(struct attachment_istream *astream,
+                                buffer_t **extra_buf_r)
 {
        struct attachment_istream_part *part = &astream->part;
-       buffer_t *extra_buf = NULL;
        struct istream *input, *base64_input;
        struct ostream *output;
        const unsigned char *data;
@@ -349,6 +349,8 @@ static int astream_decode_base64(struct attachment_istream *astream)
        int outfd;
        bool failed = FALSE;
 
+       *extra_buf_r = NULL;
+
        if (part->base64_bytes < astream->set.min_size ||
            part->temp_output->offset > part->base64_bytes +
                                        BASE64_ATTACHMENT_MAX_EXTRA_BYTES) {
@@ -410,9 +412,9 @@ static int astream_decode_base64(struct attachment_istream *astream)
 
        if (input->v_offset != part->temp_output->offset && !failed) {
                /* write the rest of the data to the message stream */
-               extra_buf = buffer_create_dynamic(default_pool, 1024);
+               *extra_buf_r = buffer_create_dynamic(default_pool, 1024);
                while ((ret = i_stream_read_more(input, &data, &size)) > 0) {
-                       buffer_append(extra_buf, data, size);
+                       buffer_append(*extra_buf_r, data, size);
                        i_stream_skip(input, size);
                }
                i_assert(ret == -1);
@@ -434,11 +436,6 @@ static int astream_decode_base64(struct attachment_istream *astream)
        o_stream_destroy(&part->temp_output);
        i_close_fd(&part->temp_fd);
        part->temp_fd = outfd;
-
-       if (extra_buf != NULL) {
-               stream_add_data(astream, extra_buf->data, extra_buf->used);
-               buffer_free(&extra_buf);
-       }
        return 0;
 }
 
@@ -450,6 +447,7 @@ astream_part_finish(struct attachment_istream *astream, const char **error_r)
        struct istream *input;
        struct ostream *output;
        string_t *digest_str;
+       buffer_t *extra_buf = NULL;
        const unsigned char *data;
        size_t size;
        int ret = 0;
@@ -484,7 +482,7 @@ astream_part_finish(struct attachment_istream *astream, const char **error_r)
                }
                if (part->base64_state == BASE64_STATE_EOM) {
                        /* base64 data looks ok. */
-                       if (astream_decode_base64(astream) < 0)
+                       if (astream_decode_base64(astream, &extra_buf) < 0)
                                part->base64_failed = TRUE;
                } else {
                        part->base64_failed = TRUE;
@@ -506,8 +504,10 @@ astream_part_finish(struct attachment_istream *astream, const char **error_r)
                info.encoded_size = part->temp_output->offset;
        }
        if (astream->set.open_attachment_ostream(&info, &output, error_r,
-                                                astream->context) < 0)
+                                                astream->context) < 0) {
+               buffer_free(&extra_buf);
                return -1;
+       }
 
        /* copy data to attachment from temp file */
        input = i_stream_create_fd(part->temp_fd, IO_BLOCK_SIZE);
@@ -526,6 +526,9 @@ astream_part_finish(struct attachment_istream *astream, const char **error_r)
        if (astream->set.close_attachment_ostream(output, ret == 0, error_r,
                                                  astream->context) < 0)
                ret = -1;
+       if (ret == 0 && extra_buf != NULL)
+               stream_add_data(astream, extra_buf->data, extra_buf->used);
+       buffer_free(&extra_buf);
        return ret;
 }