Subject: bin/31180: gzip fails catch read()/write() errors
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: Christian Biere <christianbiere@gmx.de>
List: netbsd-bugs
Date: 09/07/2005 14:48:00
>Number:         31180
>Category:       bin
>Synopsis:       gzip fails catch read()/write() errors
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Sep 07 14:48:00 +0000 2005
>Originator:     Christian Biere
>Release:        NetBSD 3.99.7
>Environment:
System: NetBSD cyclonus 3.99.7 NetBSD 3.99.7 (STARSCREAM) #4: Sat Aug 13 17:11:37 CEST 2005 bin@cyclonus:/usr/obj/objdir/sys/arch/i386/compile/STARSCREAM i386
Architecture: i386
Machine: i386
>Description:
In gzip.c and unbzip2.c the result of read() respectively write() is
assigned to variables of an unsigned integer type. Therefore, the
checks for less than zero can never succeed. Compiling with GCC
using "-W -Wall -Wformat=2" makes this obvious.

Further, these variables are visible outside of the necessary scope
which seemingly caused an inproper fix for a compiler warning in
unbzip2.c in the previous revision.

The attached patch fixes these issues and also removes the unused
second variable from handle_dir().

>How-To-Repeat:
>Fix:

Index: gzip.c
===================================================================
RCS file: /cvsroot/src/usr.bin/gzip/gzip.c,v
retrieving revision 1.73
diff -u -p -r1.73 gzip.c
--- gzip.c	28 Aug 2005 10:17:50 -0000	1.73
+++ gzip.c	7 Sep 2005 14:16:26 -0000
@@ -200,7 +200,7 @@ static	ssize_t	read_retry(int, void *, s
 #else
 static	off_t	cat_fd(unsigned char *, size_t, off_t *, int fd);
 static	void	prepend_gzip(char *, int *, char ***);
-static	void	handle_dir(char *, struct stat *);
+static	void	handle_dir(char *);
 static	void	print_verbage(const char *, const char *, off_t, off_t);
 static	void	print_test(const char *, int);
 static	void	copymodes(const char *, struct stat *);
@@ -549,7 +549,7 @@ gz_compress(int in, int out, off_t *gsiz
 	z.avail_out = BUFLEN - i;
 
 	error = deflateInit2(&z, numflag, Z_DEFLATED,
-			     -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
+			     (-MAX_WBITS), 8, Z_DEFAULT_STRATEGY);
 	if (error != Z_OK) {
 		maybe_warnx("deflateInit2 failed");
 		in_tot = -1;
@@ -1489,7 +1489,6 @@ static off_t
 cat_fd(unsigned char * prepend, size_t count, off_t *gsizep, int fd)
 {
 	char buf[BUFLEN];
-	size_t rv;
 	off_t in_tot;
 
 	in_tot = count;
@@ -1498,6 +1497,8 @@ cat_fd(unsigned char * prepend, size_t c
 		return -1;
 	}
 	for (;;) {
+		ssize_t rv;
+
 		rv = read(fd, buf, sizeof buf);
 		if (rv == 0)
 			break;
@@ -1683,7 +1684,7 @@ retry:
 	if (S_ISDIR(sb.st_mode)) {
 #ifndef SMALL
 		if (rflag)
-			handle_dir(path, &sb);
+			handle_dir(path);
 		else
 #endif
 			maybe_warnx("%s is a directory", path);
@@ -1730,7 +1731,7 @@ handle_file(char *file, struct stat *sbp
 #ifndef SMALL
 /* this is used with -r to recursively descend directories */
 static void
-handle_dir(char *dir, struct stat *sbp)
+handle_dir(char *dir)
 {
 	char *path_argv[2];
 	FTS *fts;
Index: unbzip2.c
===================================================================
RCS file: /cvsroot/src/usr.bin/gzip/unbzip2.c,v
retrieving revision 1.7
diff -u -p -r1.7 unbzip2.c
--- unbzip2.c	2 Jun 2005 01:51:58 -0000	1.7
+++ unbzip2.c	7 Sep 2005 14:16:26 -0000
@@ -6,7 +6,6 @@ static off_t
 unbzip2(int in, int out, char *pre, size_t prelen, off_t *bytes_in)
 {
 	int		ret, end_of_file;
-	size_t		n = 0;
 	off_t		bytes_out = 0;
 	bz_stream	bzs;
 	static char	*inbuf, *outbuf;
@@ -36,6 +35,8 @@ unbzip2(int in, int out, char *pre, size
 
 	while (ret != BZ_STREAM_END) {
 	        if (bzs.avail_in == 0 && !end_of_file) {
+			ssize_t	n;
+
 	                n = read(in, inbuf, BUFLEN);
 	                if (n < 0)
 	                        maybe_err("read");
@@ -57,11 +58,13 @@ unbzip2(int in, int out, char *pre, size
 	                if (ret == BZ_OK && end_of_file)
 	                        maybe_err("read");
 	                if (!tflag) {
+				ssize_t	n;
+
 	                        n = write(out, outbuf, BUFLEN - bzs.avail_out);
 	                        if (n < 0)
 	                                maybe_err("write");
+	                	bytes_out += n;
 	                }
-	                bytes_out += n;
 	                break;
 
 	        case BZ_DATA_ERROR: