]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Avoid assert-crash in istream-concat at close.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Mon, 21 Mar 2016 12:51:49 +0000 (21:51 +0900)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Tue, 29 Mar 2016 08:20:53 +0000 (11:20 +0300)
If stream was seeked to EOF, cur_input=NULL and closing the stream would cause
i_stream_concat_skip() to crash. Fixed this by making sure cur_input is never NULL.
This also adds a check to not allow seeking past EOF, but this shouldn't happen anyway.

src/lib/istream-concat.c

index 91c936f1a9f5c653a5e34e0353d961a3dcd90205..f490ec317175495796d46c53880c9dcbd4d53f72 100644 (file)
@@ -137,10 +137,7 @@ static ssize_t i_stream_concat_read(struct istream_private *stream)
        ssize_t ret;
        bool last_stream;
 
-       if (cstream->cur_input == NULL) {
-               stream->istream.stream_errno = EINVAL;
-               return -1;
-       }
+       i_assert(cstream->cur_input != NULL);
        i_stream_concat_skip(cstream);
 
        i_assert(stream->pos >= stream->skip + cstream->prev_stream_left);
@@ -274,13 +271,23 @@ static void i_stream_concat_seek(struct istream_private *stream,
 
        if (find_v_offset(cstream, &v_offset, &cstream->cur_idx) < 0) {
                /* failed */
-               cstream->cur_input = NULL;
                stream->istream.stream_errno = EINVAL;
                return;
        }
        cstream->cur_input = cstream->input[cstream->cur_idx];
-       if (cstream->cur_input != NULL)
-               i_stream_seek(cstream->cur_input, v_offset);
+       if (cstream->cur_input == NULL) {
+               /* we allow seeking to EOF, but not past it. */
+               if (v_offset != 0) {
+                       io_stream_set_error(&cstream->istream.iostream,
+                               "Seeking past EOF by %"PRIuUOFF_T" bytes", v_offset);
+                       cstream->istream.istream.stream_errno = EINVAL;
+                       return;
+               }
+               i_assert(cstream->cur_idx > 0);
+               cstream->cur_input = cstream->input[cstream->cur_idx-1];
+               v_offset = cstream->input_size[cstream->cur_idx-1];
+       }
+       i_stream_seek(cstream->cur_input, v_offset);
 }
 
 static int