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>
