Module Name:    src
Committed By:   riz
Date:           Fri Aug 19 22:30:35 UTC 2011

Modified Files:
        src/usr.bin/compress [netbsd-4-0]: zopen.c
        src/usr.bin/gzip [netbsd-4-0]: zuncompress.c

Log Message:
Pull up following revision(s) (requested by joerg in ticket #1433):
        usr.bin/compress/zopen.c: revision 1.14-1.15
        xfree/xc/lib/font/fontfile/decompress.c: revision 1.2
        xfree/xc/extras/freetype2/src/lzw/zopen.c: revision 1.2
        usr.bin/gzip/zuncompress.c: revision 1.9-1.11

Fix CVS-2011-2895, buffer overflow in decompress
provisional fix for CVS-2011-2895, buffer overflow when uncompressing
provisional fix for CVE-2011-2895, buffer overflow in decompression
set errno on overflow return.
Do proper input validation without penalizing performance.
Do proper input validation. Allow decompressing all input streams.
Increase robustness of LZW decoding to avoid buffer overflow on
arbitrary manipulated input streams in combination with uninitalised
memory.
Increase strictness of LZW parser.


To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.8.22.1 src/usr.bin/compress/zopen.c
cvs rdiff -u -r1.6 -r1.6.16.1 src/usr.bin/gzip/zuncompress.c

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

Modified files:

Index: src/usr.bin/compress/zopen.c
diff -u src/usr.bin/compress/zopen.c:1.8 src/usr.bin/compress/zopen.c:1.8.22.1
--- src/usr.bin/compress/zopen.c:1.8	Thu Aug  7 11:13:29 2003
+++ src/usr.bin/compress/zopen.c	Fri Aug 19 22:30:34 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $	*/
+/*	$NetBSD: zopen.c,v 1.8.22.1 2011/08/19 22:30:34 riz Exp $	*/
 
 /*-
  * Copyright (c) 1985, 1986, 1992, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)zopen.c	8.1 (Berkeley) 6/27/93";
 #else
-static char rcsid[] = "$NetBSD: zopen.c,v 1.8 2003/08/07 11:13:29 agc Exp $";
+static char rcsid[] = "$NetBSD: zopen.c,v 1.8.22.1 2011/08/19 22:30:34 riz Exp $";
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -488,7 +488,7 @@
 	block_compress = maxbits & BLOCK_MASK;
 	maxbits &= BIT_MASK;
 	maxmaxcode = 1L << maxbits;
-	if (maxbits > BITS) {
+	if (maxbits > BITS || maxbits < 12) {
 		errno = EFTYPE;
 		return (-1);
 	}
@@ -499,14 +499,7 @@
 		tab_suffixof(code) = (char_type) code;
 	}
 	free_ent = block_compress ? FIRST : 256;
-
-	finchar = oldcode = getcode(zs);
-	if (oldcode == -1)	/* EOF already? */
-		return (0);	/* Get out of here */
-
-	/* First code must be 8 bits = char. */
-	*bp++ = (u_char)finchar;
-	count--;
+	oldcode = -1;
 	stackp = de_stack;
 
 	while ((code = getcode(zs)) > -1) {
@@ -515,17 +508,28 @@
 			for (code = 255; code >= 0; code--)
 				tab_prefixof(code) = 0;
 			clear_flg = 1;
-			free_ent = FIRST - 1;
-			if ((code = getcode(zs)) == -1)	/* O, untimely death! */
-				break;
+			free_ent = FIRST;
+			oldcode = -1;
+			continue;
 		}
 		incode = code;
 
-		/* Special case for KwKwK string. */
+		/* Special case for kWkWk string. */
 		if (code >= free_ent) {
+			if (code > free_ent || oldcode == -1) {
+				/* Bad stream. */
+				errno = EINVAL;
+				return (-1);
+			}
 			*stackp++ = finchar;
 			code = oldcode;
 		}
+		/*
+		 * The above condition ensures that code < free_ent.
+		 * The construction of tab_prefixof in turn guarantees that
+		 * each iteration decreases code and therefore stack usage is
+		 * bound by 1 << BITS - 256.
+		 */
 
 		/* Generate output characters in reverse order. */
 		while (code >= 256) {
@@ -542,7 +546,7 @@
 		} while (stackp > de_stack);
 
 		/* Generate the new entry. */
-		if ((code = free_ent) < maxmaxcode) {
+		if ((code = free_ent) < maxmaxcode && oldcode != -1) {
 			tab_prefixof(code) = (u_short) oldcode;
 			tab_suffixof(code) = finchar;
 			free_ent = code + 1;

Index: src/usr.bin/gzip/zuncompress.c
diff -u src/usr.bin/gzip/zuncompress.c:1.6 src/usr.bin/gzip/zuncompress.c:1.6.16.1
--- src/usr.bin/gzip/zuncompress.c:1.6	Tue Nov 22 09:05:30 2005
+++ src/usr.bin/gzip/zuncompress.c	Fri Aug 19 22:30:34 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: zuncompress.c,v 1.6 2005/11/22 09:05:30 mrg Exp $ */
+/*	$NetBSD: zuncompress.c,v 1.6.16.1 2011/08/19 22:30:34 riz Exp $ */
 
 /*-
  * Copyright (c) 1985, 1986, 1992, 1993
@@ -246,7 +246,7 @@
 	zs->zs_block_compress = zs->zs_maxbits & BLOCK_MASK;
 	zs->zs_maxbits &= BIT_MASK;
 	zs->zs_maxmaxcode = 1L << zs->zs_maxbits;
-	if (zs->zs_maxbits > BITS) {
+	if (zs->zs_maxbits > BITS || zs->zs_maxbits < 12) {
 		errno = EFTYPE;
 		return (-1);
 	}
@@ -258,13 +258,7 @@
 	}
 	zs->zs_free_ent = zs->zs_block_compress ? FIRST : 256;
 
-	zs->u.r.zs_finchar = zs->u.r.zs_oldcode = getcode(zs);
-	if (zs->u.r.zs_oldcode == -1)	/* EOF already? */
-		return (0);	/* Get out of here */
-
-	/* First code must be 8 bits = char. */
-	*bp++ = (u_char)zs->u.r.zs_finchar;
-	count--;
+	zs->u.r.zs_oldcode = -1;
 	zs->u.r.zs_stackp = de_stack;
 
 	while ((zs->u.r.zs_code = getcode(zs)) > -1) {
@@ -274,17 +268,29 @@
 			    zs->u.r.zs_code--)
 				tab_prefixof(zs->u.r.zs_code) = 0;
 			zs->zs_clear_flg = 1;
-			zs->zs_free_ent = FIRST - 1;
-			if ((zs->u.r.zs_code = getcode(zs)) == -1)	/* O, untimely death! */
-				break;
+			zs->zs_free_ent = FIRST;
+			zs->u.r.zs_oldcode = -1;
+			continue;
 		}
 		zs->u.r.zs_incode = zs->u.r.zs_code;
 
 		/* Special case for KwKwK string. */
 		if (zs->u.r.zs_code >= zs->zs_free_ent) {
+			if (zs->u.r.zs_code > zs->zs_free_ent ||
+			    zs->u.r.zs_oldcode == -1) {
+				/* Bad stream. */
+				errno = EINVAL;
+				return (-1);
+			}
 			*zs->u.r.zs_stackp++ = zs->u.r.zs_finchar;
 			zs->u.r.zs_code = zs->u.r.zs_oldcode;
 		}
+		/*
+		 * The above condition ensures that code < free_ent.
+		 * The construction of tab_prefixof in turn guarantees that
+		 * each iteration decreases code and therefore stack usage is
+		 * bound by 1 << BITS - 256.
+		 */
 
 		/* Generate output characters in reverse order. */
 		while (zs->u.r.zs_code >= 256) {
@@ -301,7 +307,8 @@
 		} while (zs->u.r.zs_stackp > de_stack);
 
 		/* Generate the new entry. */
-		if ((zs->u.r.zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode) {
+		if ((zs->u.r.zs_code = zs->zs_free_ent) < zs->zs_maxmaxcode &&
+		    zs->u.r.zs_oldcode != -1) {
 			tab_prefixof(zs->u.r.zs_code) = (u_short) zs->u.r.zs_oldcode;
 			tab_suffixof(zs->u.r.zs_code) = zs->u.r.zs_finchar;
 			zs->zs_free_ent = zs->u.r.zs_code + 1;

Reply via email to