Mercurial > dovecot > original-hg > dovecot-2.1
changeset 14963:4e633c2f9738
istream-[b]zlib: Don't break if parent stream gets seeked in the middle of reads.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 09 May 2013 12:32:38 +0300 |
parents | 48199b8e99cc |
children | 4de62bda5244 |
files | src/plugins/zlib/istream-bzlib.c src/plugins/zlib/istream-zlib.c |
diffstat | 2 files changed, 59 insertions(+), 74 deletions(-) [+] |
line wrap: on
line diff
--- a/src/plugins/zlib/istream-bzlib.c Thu May 09 12:30:53 2013 +0300 +++ b/src/plugins/zlib/istream-bzlib.c Thu May 09 12:32:38 2013 +0300 @@ -15,7 +15,7 @@ bz_stream zs; uoff_t eof_offset, stream_size; - size_t prev_size, high_pos; + size_t high_pos; struct stat last_parent_statbuf; unsigned int log_errors:1; @@ -46,7 +46,7 @@ struct bzlib_istream *zstream = (struct bzlib_istream *)stream; const unsigned char *data; uoff_t high_offset; - size_t size; + size_t size, out_size; int ret; high_offset = stream->istream.v_offset + (stream->pos - stream->skip); @@ -95,42 +95,36 @@ } } - if (zstream->zs.avail_in == 0) { - /* need to read more data. try to read a full CHUNK_SIZE */ - i_stream_skip(stream->parent, zstream->prev_size); - if (i_stream_read_data(stream->parent, &data, &size, - CHUNK_SIZE-1) == -1 && size == 0) { - if (stream->parent->stream_errno != 0) { - stream->istream.stream_errno = - stream->parent->stream_errno; - } else { - i_assert(stream->parent->eof); - if (zstream->log_errors) { - bzlib_read_error(zstream, - "unexpected EOF"); - } - stream->istream.stream_errno = EINVAL; - } - return -1; + if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) { + if (stream->parent->stream_errno != 0) { + stream->istream.stream_errno = + stream->parent->stream_errno; + } else { + i_assert(stream->parent->eof); + if (zstream->log_errors) + bzlib_read_error(zstream, "unexpected EOF"); + stream->istream.stream_errno = EINVAL; } - zstream->prev_size = size; - if (size == 0) { - /* no more input */ - i_assert(!stream->istream.blocking); - return 0; - } - - zstream->zs.next_in = (char *)data; - zstream->zs.avail_in = size; + return -1; + } + if (size == 0) { + /* no more input */ + i_assert(!stream->istream.blocking); + return 0; } - size = stream->buffer_size - stream->pos; + zstream->zs.next_in = (char *)data; + zstream->zs.avail_in = size; + + out_size = stream->buffer_size - stream->pos; zstream->zs.next_out = (char *)stream->w_buffer + stream->pos; - zstream->zs.avail_out = size; + zstream->zs.avail_out = out_size; ret = BZ2_bzDecompress(&zstream->zs); - size -= zstream->zs.avail_out; - stream->pos += size; + out_size -= zstream->zs.avail_out; + stream->pos += out_size; + + i_stream_skip(stream->parent, size - zstream->zs.avail_in); switch (ret) { case BZ_OK: @@ -156,7 +150,7 @@ zstream->eof_offset = stream->istream.v_offset + (stream->pos - stream->skip); zstream->stream_size = zstream->eof_offset; - if (size == 0) { + if (out_size == 0) { stream->istream.eof = TRUE; return -1; } @@ -164,11 +158,11 @@ default: i_fatal("BZ2_bzDecompress() failed with %d", ret); } - if (size == 0) { + if (out_size == 0) { /* read more input */ return i_stream_bzlib_read(stream); } - return size; + return out_size; } static void i_stream_bzlib_init(struct bzlib_istream *zstream) @@ -203,7 +197,6 @@ stream->skip = stream->pos = 0; stream->istream.v_offset = 0; zstream->high_pos = 0; - zstream->prev_size = 0; (void)BZ2_bzDecompressEnd(&zstream->zs); i_stream_bzlib_init(zstream);
--- a/src/plugins/zlib/istream-zlib.c Thu May 09 12:30:53 2013 +0300 +++ b/src/plugins/zlib/istream-zlib.c Thu May 09 12:32:38 2013 +0300 @@ -119,6 +119,7 @@ pos += 2; } i_stream_skip(stream->parent, pos); + zstream->prev_size = 0; return 1; } @@ -169,7 +170,7 @@ struct zlib_istream *zstream = (struct zlib_istream *)stream; const unsigned char *data; uoff_t high_offset; - size_t size; + size_t size, out_size; int ret; high_offset = stream->istream.v_offset + (stream->pos - stream->skip); @@ -205,7 +206,6 @@ if (ret <= 0) return ret; zstream->header_read = TRUE; - zstream->prev_size = 0; } if (stream->pos < zstream->high_pos) { @@ -245,44 +245,39 @@ } } - if (zstream->zs.avail_in == 0) { - /* need to read more data. try to read a full CHUNK_SIZE */ - i_stream_skip(stream->parent, zstream->prev_size); - if (i_stream_read_data(stream->parent, &data, &size, - CHUNK_SIZE-1) == -1 && size == 0) { - if (stream->parent->stream_errno != 0) { - stream->istream.stream_errno = - stream->parent->stream_errno; - } else { - i_assert(stream->parent->eof); - if (zstream->log_errors) { - zlib_read_error(zstream, - "unexpected EOF"); - } - stream->istream.stream_errno = EPIPE; - } - return -1; + if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) { + if (stream->parent->stream_errno != 0) { + stream->istream.stream_errno = + stream->parent->stream_errno; + } else { + i_assert(stream->parent->eof); + if (zstream->log_errors) + zlib_read_error(zstream, "unexpected EOF"); + stream->istream.stream_errno = EPIPE; } - zstream->prev_size = size; - if (size == 0) { - /* no more input */ - i_assert(!stream->istream.blocking); - return 0; - } - - zstream->zs.next_in = (void *)data; - zstream->zs.avail_in = size; + return -1; + } + if (size == 0) { + /* no more input */ + i_assert(!stream->istream.blocking); + return 0; } - size = stream->buffer_size - stream->pos; + zstream->zs.next_in = (void *)data; + zstream->zs.avail_in = size; + + out_size = stream->buffer_size - stream->pos; zstream->zs.next_out = stream->w_buffer + stream->pos; - zstream->zs.avail_out = size; + zstream->zs.avail_out = out_size; ret = inflate(&zstream->zs, Z_SYNC_FLUSH); - size -= zstream->zs.avail_out; + out_size -= zstream->zs.avail_out; zstream->crc32 = crc32_data_more(zstream->crc32, - stream->w_buffer + stream->pos, size); - stream->pos += size; + stream->w_buffer + stream->pos, + out_size); + stream->pos += out_size; + + i_stream_skip(stream->parent, size - zstream->zs.avail_in); switch (ret) { case Z_OK: @@ -304,10 +299,7 @@ zstream->eof_offset = stream->istream.v_offset + (stream->pos - stream->skip); zstream->stream_size = zstream->eof_offset; - i_stream_skip(stream->parent, - zstream->prev_size - zstream->zs.avail_in); zstream->zs.avail_in = 0; - zstream->prev_size = 0; if (!zstream->trailer_read) { /* try to read and verify the trailer, we might not @@ -319,11 +311,11 @@ default: i_fatal("inflate() failed with %d", ret); } - if (size == 0) { + if (out_size == 0) { /* read more input */ return i_stream_zlib_read(stream); } - return size; + return out_size; } static void i_stream_zlib_init(struct zlib_istream *zstream)