On Mon, Dec 07, 2015 at 01:36:22AM -0500, Michael McConville wrote:
> This isn't a grave issue, but I came across it while exploring integer
> overflow and think it's worth sharing.
>
> grep represents line numbers with an int, which predictably overflows
> for inputs with >= 2^31 newlines. This is easy to demonstrate using the
> -n option and a debugging printf.
>
> The below diff fixes this, and tunes up a for loop while I'm in there.
how does this fix work on 32-bit platforms? Better use offset_t. Also,
use %zu to print size_t's. The for loop change, I dunno.
-Otto
>
> ok?
>
>
> Index: grep.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/grep/grep.h,v
> retrieving revision 1.22
> diff -u -p -r1.22 grep.h
> --- grep.h 16 Mar 2015 13:26:52 -0000 1.22
> +++ grep.h 7 Dec 2015 06:26:55 -0000
> @@ -43,7 +43,7 @@
>
> typedef struct {
> size_t len;
> - int line_no;
> + size_t line_no;
> off_t off;
> char *file;
> char *dat;
> Index: util.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/grep/util.c,v
> retrieving revision 1.50
> diff -u -p -r1.50 util.c
> --- util.c 25 Jun 2015 02:04:08 -0000 1.50
> +++ util.c 7 Dec 2015 06:26:55 -0000
> @@ -124,7 +124,7 @@ procfile(char *fn)
>
> if (Bflag > 0)
> initqueue();
> - for (c = 0; c == 0 || !(lflag || qflag); ) {
> + for (c = 0; c == 0 || !(lflag || qflag); c += t) {
> ln.off += ln.len + 1;
> if ((ln.dat = grep_fgetln(f, &ln.len)) == NULL)
> break;
> @@ -138,7 +138,6 @@ procfile(char *fn)
> enqueue(&ln);
> linesqueued++;
> }
> - c += t;
> }
> if (Bflag > 0)
> clearqueue();
> @@ -623,7 +622,7 @@ printline(str_t *line, int sep, regmatch
> if (nflag) {
> if (n)
> putchar(sep);
> - printf("%d", line->line_no);
> + printf("%llu", (unsigned long long)line->line_no);
> ++n;
> }
> if (bflag) {