Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 May 2001 18:40:31 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Mike Heffner <mheffner@cowpie.acm.vt.edu>
Cc:        freebsd-audit@FreeBSD.ORG
Subject:   Re: cmp(1) patch
Message-ID:  <Pine.BSF.4.21.0105281757490.485-100000@besplex.bde.org>
In-Reply-To: <20010527232926.A85869@cowpie.acm.vt.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 27 May 2001, Mike Heffner wrote:

> BDECFLAGS cleanup, respect -s flag in one place, return instead of
> exit() at end of main. Please review.
> 
> Index: cmp.c
> ===================================================================
> RCS file: /home/ncvs/src/usr.bin/cmp/cmp.c,v
> retrieving revision 1.9
> diff -u -r1.9 cmp.c
> --- cmp.c	2000/07/25 13:01:34	1.9
> +++ cmp.c	2001/05/26 21:57:56
> ...
> @@ -117,9 +118,13 @@
>  			exit(1);
>  	}
>  	if (strcmp(file2 = argv[1], "-") == 0) {
> -		if (special)
> -			errx(ERR_EXIT,
> +		if (special) {
> +			if (!sflag)
> +				errx(ERR_EXIT,
>  				"standard input may only be specified once");
> +			else
> +				exit(1);
> +		}
>  		special = 1;
>  		fd2 = 0;
>  		file2 = "stdin";

This change seems to be just a bug.  -s is only required (by POSIX) to
suppress output to stdout (in particular, it must suppress the message
about differing files).  The above suppresses output to stderr for a
usage error.  Output to stderr is still done for other usage errors.

> ...
> @@ -160,14 +165,14 @@
>  	else {
>  		if (zflag && sb1.st_size != sb2.st_size) {
>  			if (!sflag)
> -				(void) printf("%s %s differ: size\n",
> +				(void)printf("%s %s differ: size\n",
>  				    file1, file2);
>  			exit(DIFF_EXIT);
>  		}
>  		c_regular(fd1, file1, skip1, sb1.st_size,
>  		    fd2, file2, skip2, sb2.st_size);
>  	}
> -	exit(0);
> +	return (0);

gcc should understand that exit() doesn't return, and not warn for exit(0).

> Index: regular.c
> ===================================================================
> RCS file: /home/ncvs/src/usr.bin/cmp/regular.c,v
> retrieving revision 1.10
> diff -u -r1.10 regular.c
> --- regular.c	2000/06/20 20:28:40	1.10
> +++ regular.c	2001/05/26 21:57:57
> ...
> @@ -81,8 +81,10 @@
>  	off2 = ROUNDPAGE(skip2);
>  
>  	length = MIN(len1, len2);
> -	if (length > SIZE_T_MAX)
> -		return (c_special(fd1, file1, skip1, fd2, file2, skip2));
> +	if (length > SIZE_T_MAX) {
> +		c_special(fd1, file1, skip1, fd2, file2, skip2);
> +		return;
> +	}
>  
>  	if ((p1 = (u_char *)mmap(NULL, (size_t)len1 + skip1 % pagesize,
>  	    PROT_READ, MAP_SHARED, fd1, off1)) == (u_char *)MAP_FAILED)

This code has several bugs that should be fixed someday:
- casting len1 (and later len2) to size_t may overflow.  We only checked
  that MIN(len1, len2) fits in a size_t.  mmap()'ing more than `length'
  (rounded up a little?) bytes is a bug.  The CSRG version was missing
  this bug, but apparently had others.
- adding skip1 % pagesize may cause another overflow.
- the mmap() (or the later one) may fail for various reasons.  E.g., the
  files may have length 3GB each.  It is impossible for mmap() to map
  two files of length 3GB each on i386's, since there is at most 4GB of
  vm to map them in (the mmap() will actually fail much earlier, near
  2 * 1.25GB).  c_special() should be used if either of the mmap()s fails.
  Note that the SIZE_T_MAX check isn't intended to make mmap() work.  It
  is just intended to prevent overflow when the size arg for mmap is
  squeezed into a size_t.  But even that is botched here.

Many utilities that call mmap() have similar bugs.  One already has a wrong
fix for mmap() failure.

> @@ -101,10 +103,12 @@
>  		if ((ch = *p1) != *p2) {
>  			if (xflag) {
>  				dfound = 1;
> -				(void)printf("%08qx %02x %02x\n", byte - 1, ch, *p2);
> +				(void)printf("%08llx %02x %02x\n",
> +				    (long long)byte - 1, ch, *p2);

Using hard "long long" breaks ISO C (C90) support, not to mention K&R
support, and is also wrong for C99.  intmax_t should be used for C99,
but we don't have either intma_t or a C99 compiler yet.

There are still printf format errors here.  %llx is for unsigned type, but
both the type of `byte' and "long long" are signed types.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0105281757490.485-100000>