From nb@ravenbrook.com Wed Aug  4 04:46:18 1999
Return-Path: <nb@ravenbrook.com>
Received: from raven.ravenbrook.com (raven.ravenbrook.com [193.112.142.1])
	by hub.freebsd.org (Postfix) with ESMTP id 6CD9F15108
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  4 Aug 1999 04:46:06 -0700 (PDT)
	(envelope-from nb@ravenbrook.com)
Received: (from nb@localhost)
	by raven.ravenbrook.com (8.9.3/8.9.3) id MAA13467;
	Wed, 4 Aug 1999 12:45:18 +0100 (BST)
Message-Id: <199908041145.MAA13467@raven.ravenbrook.com>
Date: Wed, 4 Aug 1999 12:45:18 +0100 (BST)
From: Nicholas Barnes <nb@ravenbrook.com>
Reply-To: nb@ravenbrook.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: /usr/bin/wc overflows at 2^32
X-Send-Pr-Version: 3.2

>Number:         12959
>Category:       bin
>Synopsis:       /usr/bin/wc overflows at 2^32
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    sheldonh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug  4 04:50:00 PDT 1999
>Closed-Date:    Fri Aug 6 07:41:27 PDT 1999
>Last-Modified:  Fri Aug  6 07:42:05 PDT 1999
>Originator:     Nicholas Barnes
>Release:        FreeBSD 2.2.8-RELEASE i386
>Organization:
Ravenbrook Limited
>Environment:

	Generic 2.2.8 PC.

>Description:

	/usr/bin/wc overflows at 2^32, so passing it a big file
        (or stream) gives bogus results.

>How-To-Repeat:

	$ dd if=/dev/zero bs=1m count=4097 | wc
        4097+0 records in
        4097+0 records out
        4296015872 bytes transferred in 614.248991 secs (6993932 bytes/sec)
         1048576
        $
>Fix:
	
        I'm sure a simple hack in the wc sources could make the
        counters 64-bit.

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: sheldonh 
State-Changed-When: Wed Aug 4 06:52:38 PDT 1999 
State-Changed-Why:  
The internal counters are already u_long. Presumeably, you want them to  
be quad_t? Could you try it and see what the performance hit is like on  
an Intel machine? 


Responsible-Changed-From-To: freebsd-bugs->sheldonh 
Responsible-Changed-By: sheldonh 
Responsible-Changed-When: Wed Aug 4 06:52:38 PDT 1999 
Responsible-Changed-Why:  
I'll take this one. 

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: nb@ravenbrook.com
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/12959: /usr/bin/wc overflows at 2^32 
Date: Wed, 04 Aug 1999 16:30:21 +0200

 I've tested the following diff for performance and see no noticeable
 loss. I will say that I think it's perverse to demand the use of a
 quad_int to store the number of lines in a file and a little less
 perverse to do the same for the number of words, but since it doesn't
 seem to cost us much, it's probably okay.
 
 Would you like to test this? Paticularly, I haven't checked that the
 printf()'s all do the right thing in all cases.
 
 Ciao,
 Sheldon.
 
 Index: wc.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/wc/wc.c,v
 retrieving revision 1.8
 diff -u -d -r1.8 wc.c
 --- wc.c	1997/08/25 06:44:59	1.8
 +++ wc.c	1999/08/04 14:24:53
 @@ -58,7 +58,7 @@
  #include <string.h>
  #include <unistd.h>
  
 -u_long tlinect, twordct, tcharct;
 +quad_t tlinect, twordct, tcharct;
  int doline, doword, dochar;
  
  int cnt __P((char *));
 @@ -70,7 +70,7 @@
  	char *argv[];
  {
  	register int ch;
 -	int errors, total;
 +	quad_t errors, total;
  
  	(void) setlocale(LC_CTYPE, "");
  
 @@ -114,11 +114,11 @@
  
  	if (total > 1) {
  		if (doline)
 -			(void)printf(" %7ld", tlinect);
 +			(void)printf(" %7qu", tlinect);
  		if (doword)
 -			(void)printf(" %7ld", twordct);
 +			(void)printf(" %7qu", twordct);
  		if (dochar)
 -			(void)printf(" %7ld", tcharct);
 +			(void)printf(" %7qu", tcharct);
  		(void)printf(" total\n");
  	}
  	exit(errors == 0 ? 0 : 1);
 @@ -131,7 +131,7 @@
  	register u_char *p, ch;
  	register short gotsp;
  	register int len;
 -	register u_long linect, wordct, charct;
 +	register quad_t linect, wordct, charct;
  	struct stat sb;
  	int fd;
  	u_char buf[MAXBSIZE];
 @@ -165,10 +165,10 @@
  						++linect;
  			}
  			tlinect += linect;
 -			(void)printf(" %7lu", linect);
 +			(void)printf(" %7qu", linect);
  			if (dochar) {
  				tcharct += charct;
 -				(void)printf(" %7lu", charct);
 +				(void)printf(" %7qu", charct);
  			}
  			(void)close(fd);
  			return (0);
 @@ -219,15 +219,15 @@
  	}
  	if (doline) {
  		tlinect += linect;
 -		(void)printf(" %7lu", linect);
 +		(void)printf(" %7qu", linect);
  	}
  	if (doword) {
  		twordct += wordct;
 -		(void)printf(" %7lu", wordct);
 +		(void)printf(" %7qu", wordct);
  	}
  	if (dochar) {
  		tcharct += charct;
 -		(void)printf(" %7lu", charct);
 +		(void)printf(" %7qu", charct);
  	}
  	(void)close(fd);
  	return (0);
 

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/12959: /usr/bin/wc overflows at 2^32 
Date: Wed, 04 Aug 1999 16:36:58 +0200

 Nick pointed me at the NetBSD changes, which highlight a glaring error
 in my 2 minute noodles diff (the printf conversion specifiers).
 
 Ciao,
 Sheldon.
 
 Index: wc.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/wc/wc.c,v
 retrieving revision 1.8
 diff -u -d -r1.8 wc.c
 --- wc.c	1997/08/25 06:44:59	1.8
 +++ wc.c	1999/08/04 14:24:53
 @@ -58,7 +58,7 @@
  #include <string.h>
  #include <unistd.h>
  
 -u_long tlinect, twordct, tcharct;
 +quad_t tlinect, twordct, tcharct;
  int doline, doword, dochar;
  
  int cnt __P((char *));
 @@ -70,7 +70,7 @@
  	char *argv[];
  {
  	register int ch;
 -	int errors, total;
 +	quad_t errors, total;
  
  	(void) setlocale(LC_CTYPE, "");
  
 @@ -114,11 +114,11 @@
  
  	if (total > 1) {
  		if (doline)
 -			(void)printf(" %7ld", tlinect);
 +			(void)printf(" %7qd", tlinect);
  		if (doword)
 -			(void)printf(" %7ld", twordct);
 +			(void)printf(" %7qd", twordct);
  		if (dochar)
 -			(void)printf(" %7ld", tcharct);
 +			(void)printf(" %7qd", tcharct);
  		(void)printf(" total\n");
  	}
  	exit(errors == 0 ? 0 : 1);
 @@ -131,7 +131,7 @@
  	register u_char *p, ch;
  	register short gotsp;
  	register int len;
 -	register u_long linect, wordct, charct;
 +	register quad_t linect, wordct, charct;
  	struct stat sb;
  	int fd;
  	u_char buf[MAXBSIZE];
 @@ -165,10 +165,10 @@
  						++linect;
  			}
  			tlinect += linect;
 -			(void)printf(" %7lu", linect);
 +			(void)printf(" %7qd", linect);
  			if (dochar) {
  				tcharct += charct;
 -				(void)printf(" %7lu", charct);
 +				(void)printf(" %7qd", charct);
  			}
  			(void)close(fd);
  			return (0);
 @@ -219,15 +219,15 @@
  	}
  	if (doline) {
  		tlinect += linect;
 -		(void)printf(" %7lu", linect);
 +		(void)printf(" %7qd", linect);
  	}
  	if (doword) {
  		twordct += wordct;
 -		(void)printf(" %7lu", wordct);
 +		(void)printf(" %7qd", wordct);
  	}
  	if (dochar) {
  		tcharct += charct;
 -		(void)printf(" %7lu", charct);
 +		(void)printf(" %7qd", charct);
  	}
  	(void)close(fd);
  	return (0);
 

From: Sheldon Hearn <sheldonh@uunet.co.za>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: bin/12959: /usr/bin/wc overflows at 2^32 
Date: Wed, 04 Aug 1999 16:39:24 +0200

 *sigh*
 
 Let me slow down, have a cup of coffee and then merge NetBSD's changes
 properly -- NetBSD is a lot better at getting past bde than OpenBSD.
 
 Ciao,
 Sheldon.
 
State-Changed-From-To: feedback->closed 
State-Changed-By: sheldonh 
State-Changed-When: Fri Aug 6 07:41:27 PDT 1999 
State-Changed-Why:  
Fixed in rev 1.9 of wc.c . 
>Unformatted:
