dovecot-2.2: istream-[b]zlib: Don't break if parent stream gets ...

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 23 20:54:19 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/ba63c27667ff
changeset: 16315:ba63c27667ff
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 23 20:53:53 2013 +0300
description:
istream-[b]zlib: Don't break if parent stream gets seeked in the middle of reads.

diffstat:

 src/lib-compression/istream-bzlib.c |  65 +++++++++++++++-------------------
 src/lib-compression/istream-zlib.c  |  68 ++++++++++++++++--------------------
 2 files changed, 59 insertions(+), 74 deletions(-)

diffs (243 lines):

diff -r 6d19a0f32a1b -r ba63c27667ff src/lib-compression/istream-bzlib.c
--- a/src/lib-compression/istream-bzlib.c	Tue Apr 23 20:51:34 2013 +0300
+++ b/src/lib-compression/istream-bzlib.c	Tue Apr 23 20:53:53 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;
@@ -49,7 +49,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);
@@ -98,42 +98,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:
@@ -159,7 +153,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;
 		}
@@ -167,11 +161,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)
@@ -206,7 +200,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);
diff -r 6d19a0f32a1b -r ba63c27667ff src/lib-compression/istream-zlib.c
--- a/src/lib-compression/istream-zlib.c	Tue Apr 23 20:51:34 2013 +0300
+++ b/src/lib-compression/istream-zlib.c	Tue Apr 23 20:53:53 2013 +0300
@@ -122,6 +122,7 @@
 		pos += 2;
 	}
 	i_stream_skip(stream->parent, pos);
+	zstream->prev_size = 0;
 	return 1;
 }
 
@@ -172,7 +173,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);
@@ -208,7 +209,6 @@
 		if (ret <= 0)
 			return ret;
 		zstream->header_read = TRUE;
-		zstream->prev_size = 0;
 	}
 
 	if (stream->pos < zstream->high_pos) {
@@ -248,44 +248,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:
@@ -307,10 +302,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
@@ -322,11 +314,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)


More information about the dovecot-cvs mailing list