dovecot-2.2: lib-compression: gz compression didn't handle multi...

dovecot at dovecot.org dovecot at dovecot.org
Wed May 7 10:03:25 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/625249382745
changeset: 17328:625249382745
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 07 12:27:36 2014 +0300
description:
lib-compression: gz compression didn't handle multiple flushes correctly.

diffstat:

 src/lib-compression/ostream-zlib.c |  33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

diffs (93 lines):

diff -r 2fe36249c62b -r 625249382745 src/lib-compression/ostream-zlib.c
--- a/src/lib-compression/ostream-zlib.c	Wed May 07 12:26:58 2014 +0300
+++ b/src/lib-compression/ostream-zlib.c	Wed May 07 12:27:36 2014 +0300
@@ -141,12 +141,18 @@
 			}
 		}
 
-		switch (deflate(zs, flush)) {
+		ret = deflate(zs, flush);
+		switch (ret) {
 		case Z_OK:
 		case Z_BUF_ERROR:
 			break;
+		case Z_STREAM_ERROR:
+			i_assert(zstream->gz);
+			i_panic("zlib.write(%s) failed: Can't write more data to .gz after flushing",
+				o_stream_get_name(&zstream->ostream.ostream));
 		default:
-			i_unreached();
+			i_panic("zlib.write(%s) failed with unexpected code %d",
+				o_stream_get_name(&zstream->ostream.ostream), ret);
 		}
 	}
 	size -= zs->avail_in;
@@ -158,12 +164,13 @@
 	return size;
 }
 
-static int o_stream_zlib_send_flush(struct zlib_ostream *zstream)
+static int
+o_stream_zlib_send_flush(struct zlib_ostream *zstream, bool final)
 {
 	z_stream *zs = &zstream->zs;
 	unsigned int len;
 	bool done = FALSE;
-	int ret;
+	int ret, flush;
 
 	if (zs->avail_in != 0) {
 		i_assert(zstream->ostream.ostream.last_failed_errno != 0);
@@ -182,6 +189,9 @@
 	if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0)
 		return ret;
 
+	flush = !zstream->gz ? Z_SYNC_FLUSH :
+		(final ? Z_FINISH : Z_NO_FLUSH);
+
 	i_assert(zstream->outbuf_used == 0);
 	do {
 		len = sizeof(zstream->outbuf) - zs->avail_out;
@@ -196,7 +206,7 @@
 				break;
 		}
 
-		switch (deflate(zs, zstream->gz ? Z_FINISH : Z_SYNC_FLUSH)) {
+		switch (deflate(zs, flush)) {
 		case Z_OK:
 		case Z_BUF_ERROR:
 			break;
@@ -208,9 +218,12 @@
 		}
 	} while (zs->avail_out != sizeof(zstream->outbuf));
 
-	if (o_stream_zlib_send_gz_trailer(zstream) < 0)
-		return -1;
-	zstream->flushed = TRUE;
+	if (final) {
+		if (o_stream_zlib_send_gz_trailer(zstream) < 0)
+			return -1;
+	}
+	if (final || flush != Z_NO_FLUSH)
+		zstream->flushed = TRUE;
 	return 0;
 }
 
@@ -219,7 +232,7 @@
 	struct zlib_ostream *zstream = (struct zlib_ostream *)stream;
 	int ret;
 
-	if (o_stream_zlib_send_flush(zstream) < 0)
+	if (o_stream_zlib_send_flush(zstream, TRUE) < 0)
 		return -1;
 
 	ret = o_stream_flush(stream->parent);
@@ -254,7 +267,7 @@
 	stream->ostream.offset += bytes;
 
 	if (!zstream->ostream.corked && i == iov_count) {
-		if (o_stream_zlib_send_flush(zstream) < 0)
+		if (o_stream_zlib_send_flush(zstream, FALSE) < 0)
 			return -1;
 	}
 	/* avail_in!=0 check is used to detect errors. if it's non-zero here


More information about the dovecot-cvs mailing list