Module Name:    src
Committed By:   drochner
Date:           Thu Feb 17 17:10:18 UTC 2011

Modified Files:
        src/sys/opencrypto: deflate.c

Log Message:
The decompressor in sys/net/zlib.c has a bug: It returns Z_BUF_ERROR after
a successful decompression in rare cases. A necessary but not sufficient
condition seems to be that the decompressed data end exactly at the end
of an allocated output buffer. (I can reproduce this reliably with
a userland program built against kernel zlib. Userland libz is much
newer and not affected.)
Since kernel zlib is based on an old version and heavily modified, I don't
dare to touch it. So catch this case in the wrapper.
Being here, reorder deflate/inflate error handling and add comments
to make understandable what is tested and why.


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/opencrypto/deflate.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/opencrypto/deflate.c
diff -u src/sys/opencrypto/deflate.c:1.15 src/sys/opencrypto/deflate.c:1.16
--- src/sys/opencrypto/deflate.c:1.15	Wed Feb 16 19:08:57 2011
+++ src/sys/opencrypto/deflate.c	Thu Feb 17 17:10:18 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: deflate.c,v 1.15 2011/02/16 19:08:57 drochner Exp $ */
+/*	$NetBSD: deflate.c,v 1.16 2011/02/17 17:10:18 drochner Exp $ */
 /*	$FreeBSD: src/sys/opencrypto/deflate.c,v 1.1.2.1 2002/11/21 23:34:23 sam Exp $	*/
 /* $OpenBSD: deflate.c,v 1.3 2001/08/20 02:45:22 hugh Exp $ */
 
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: deflate.c,v 1.15 2011/02/16 19:08:57 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: deflate.c,v 1.16 2011/02/17 17:10:18 drochner Exp $");
 
 #include <sys/types.h>
 #include <sys/malloc.h>
@@ -125,10 +125,22 @@
 	for (;;) {
 		error = decomp ? inflate(&zbuf, Z_SYNC_FLUSH) :
 				 deflate(&zbuf, Z_FINISH);
-		if (error != Z_OK && error != Z_STREAM_END)
+		if (error == Z_STREAM_END) /* success */
+			break;
+		/*
+		 * XXX compensate for two problems:
+		 * -Former versions of this code didn't set Z_FINISH
+		 *  on compression, so the compressed data are not correctly
+		 *  terminated and the decompressor doesn't get Z_STREAM_END.
+		 *  Accept such packets for interoperability.
+		 * -sys/net/zlib.c has a bug which makes that Z_BUF_ERROR is
+		 *  set after successful decompression under rare conditions.
+		 */
+		else if (decomp && (error == Z_OK || error == Z_BUF_ERROR)
+			 && zbuf.avail_in == 0 && zbuf.avail_out != 0)
+				break;
+		else if (error != Z_OK)
 			goto bad;
-		else if (zbuf.avail_in == 0 && zbuf.avail_out != 0)
-			goto end;
 		else if (zbuf.avail_out == 0) {
 			if (i == len) {
 				len += ZBUF;
@@ -146,11 +158,9 @@
 			buf[i].size = size;
 			zbuf.avail_out = buf[i].size;
 			i++;
-		} else
-			goto bad;
+		}
 	}
 
-end:
 	result = count = zbuf.total_out;
 
 	if (i != 1) { /* copy everything into one buffer */

Reply via email to