Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 May 2001 12:02:08 -0400
From:      Mike Heffner <mheffner@cowpie.acm.vt.edu>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        freebsd-audit@freebsd.org
Subject:   Re: cmp(1) patch
Message-ID:  <20010528120208.A87924@cowpie.acm.vt.edu>
In-Reply-To: <Pine.BSF.4.21.0105281757490.485-100000@besplex.bde.org>; from bde@zeta.org.au on Mon, May 28, 2001 at 06:40:31PM %2B1000
References:  <20010527232926.A85869@cowpie.acm.vt.edu> <Pine.BSF.4.21.0105281757490.485-100000@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, May 28, 2001 at 06:40:31PM +1000, Bruce Evans wrote:
| 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.

However it is also used to suppress output from open and fstat
failing, but I guess in the case of scripts this might be
favorable. I'll reverse this part since it's a usage error though.

| 
| > ...
| > @@ -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).

Ok, I just thought return looked better at the end of main =), but I'll
leave exit() in there.

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

Changing the 'if (length > SIZE_T_MAX)' to 'if (MAX(len1, len2) >
SIZE_T_MAX)' (plus possibly the skip lengths) should fix the
overflowing on size_t issue right?

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

I'll try to address this issue, to call c_special when mmap fails and
fix the overflow checks, when I redo the patch.

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

So should it be left with `%qx', or should byte be typecasted unsigned and use
`%llx'?

Thanks for looking at this by the way ;)

-- 

  Mike Heffner               <mheffner@vt.edu>
  Fredericksburg, VA       <mikeh@FreeBSD.org>
      http://filebox.vt.edu/users/mheffner

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?20010528120208.A87924>