Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/opencrypto The decompressor in sys/net/zlib.c has a bug:...



details:   https://anonhg.NetBSD.org/src/rev/c639c2c8ea75
branches:  trunk
changeset: 762214:c639c2c8ea75
user:      drochner <drochner%NetBSD.org@localhost>
date:      Thu Feb 17 17:10:18 2011 +0000

description:
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.

diffstat:

 sys/opencrypto/deflate.c |  26 ++++++++++++++++++--------
 1 files changed, 18 insertions(+), 8 deletions(-)

diffs (57 lines):

diff -r 0e67ff3f347c -r c639c2c8ea75 sys/opencrypto/deflate.c
--- a/sys/opencrypto/deflate.c  Thu Feb 17 17:07:55 2011 +0000
+++ b/sys/opencrypto/deflate.c  Thu Feb 17 17:10:18 2011 +0000
@@ -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 */



Home | Main Index | Thread Index | Old Index