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) {

Reply via email to