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: