On Mon, Dec 07, 2015 at 02:32:50AM -0500, Michael McConville wrote: > Otto Moerbeek wrote: > > 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. > > Good catch, thanks. > > Does this look better? Or is PRId64 preferred for off_t?
I don't think off_t is related to ptrdiff_t. The only thing defined for off_t is that it's a signed integer type, meant to express offsets in a file. Just cast to long long and use %lld. And please remove the unrelated for loop change. -Otto > > > 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 07:30:52 -0000 > @@ -43,7 +43,7 @@ > > typedef struct { > size_t len; > - int line_no; > + off_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 07:30:52 -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("%jd", line->line_no); > ++n; > } > if (bflag) {