Oops, sorry, it was already committed, I took the wrong mail.
Sorry for the noise

On Wed, May 27, 2026 at 10:02:33AM +0200, Renaud Allard wrote:
> From: Renaud Allard <[email protected]>
> To: [email protected]
> Subject: Fwd: [ col(1): signed integer overflow in flush_line() sort ]
> Date: Wed, 27 May 2026 10:02:33 +0200
> 
> Hello,
> 
> Small OK ping for this one.
> 
> 
> ----- Forwarded message from Renaud Allard <[email protected]> -----
> 
> > From: Renaud Allard <[email protected]>
> > To: [email protected]
> > Subject: col(1): signed integer overflow in flush_line() sort
> > Date: Tue, 31 Mar 2026 14:46:11 +0200
> > 
> > The counting sort in flush_line() uses int for the count array,
> > save, and tot variables.  When reverse line feeds (\v) cause many
> > characters to be placed at the same column, these overflow.
> > 
> > The sort works by counting characters per column, then computing
> > a running total as indices into a sorted output array:
> > 
> >   static int *count, save, tot;
> >   ...
> >   for (i = nchars, c = l->l_line; i-- > 0; c++)
> >       count[c->c_column]++;
> >   ...
> >   for (tot = 0, i = 0; i <= l->l_max_col; i++) {
> >       save = count[i];
> >       count[i] = tot;
> >       tot += save;
> >   }
> > 
> > nchars (the total character count) is size_t.  The per-column
> > counts in count[] and the running total in tot accumulate to
> > nchars.  When nchars exceeds INT_MAX, both count[i]++ and
> > tot += save overflow signed int.
> > 
> > The 5-byte input "1\v2\n\n" triggers the overflow: the vertical
> > tab causes characters to be placed at the same column via reverse
> > line feed, requiring the sort path.
> > 
> > Fix: change count, save, and tot from int to size_t, matching the
> > existing nchars type.  Also use sizeof(*count) in the allocation
> > for consistency.
> > 
> > Found by AFL++ fuzzing with UBSan.
> > 
> > Index: usr.bin/col/col.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/col/col.c,v
> > retrieving revision 1.20
> > diff -u -p -r1.20 col.c
> > --- usr.bin/col/col.c       4 Dec 2022 23:50:47 -0000       1.20
> > +++ usr.bin/col/col.c
> > @@ -388,7 +388,7 @@ flush_line(LINE *l)
> >     if (l->l_needs_sort) {
> >             static CHAR *sorted;
> >             static size_t count_size, i, sorted_size;
> > -           static int *count, save, tot;
> > +           static size_t *count, save, tot;
> > 
> >             /*
> >              * Do an O(n) sort on l->l_line by column being careful to
> > @@ -402,7 +402,7 @@ flush_line(LINE *l)
> >             if (l->l_max_col >= count_size) {
> >                     count_size = l->l_max_col + 1;
> >                     count = xreallocarray(count,
> > -                       count_size, sizeof(int));
> > +                       count_size, sizeof(*count));
> >             }
> >             memset(count, 0, sizeof(*count) * (l->l_max_col + 1));
> >             for (i = nchars, c = l->l_line; i-- > 0; c++)
> > 
> 
> ----- End forwarded message -----

Reply via email to