Package: bsdmainutils
Version: 9.0.5
Severity: important

If an input line to col exceeds 32k characters, an integer overflow may
cause col to attempt illegal memory reads and writes, and will also
truncate output lines.

This can easily be seen using the following command:

    valgrind col < <(printf 'xx\b\b'; printf z%.0s {1..131072}) | wc -c

valgrind will report illegal reads and writes, and wc will show the
truncated output.

The following problem description is copied from a bug report to FreeBSD (
http://www.freebsd.org/cgi/query-pr.cgi?pr=186282), which uses a similar
source for col (the line numbers are different but the problem is the same).

----- COPY STARTS

At line 78 of col.c
(http://svnweb.freebsd.org/base/head/usr.bin/col/col.c),the c_column
member of the CHAR struct is declared as short:

short c_column; /* column character is in */

This value is set (for each character) at line 299 from cur_col

c->c_column = cur_col;

But cur_col is an int.

Consequently, if the input has a line of more than 32768 characters, the
assignment to c->c_column will produce an integer overflow, producing two
errors: first, the value of c->column may become negative, which may cause
random memory to be overwritten; second, it may limit the line's output
size to 32768 characters, overlaying portions of the line over other
portions.

The more serious issue, the buffer overrun, will be triggered in the case
that l->l_needs_sort is set to true at line 306, which will happen if input
characters are out of sequence as a result of backspaces in the input (more
than one consecutive backspace is required to trigger this condition). In
that case, control flow will eventually reach line 423:

count[c->c_column]++;

which may use a negative integer from c->c_column to index the malloc'd
region count.

While this is not likely to be exploitable, since the memory overwrite is
an increment rather than a set, it could certainly cause unpredictable
behaviour. In addition, the integer overflow will cause other problems for
input containing long lines.

--- COPY ENDS

As indicate in the FreeBSD bug report, the easiest (but insufficient) fix
is to make c_column a short rather than an int. However, that will still
result in integer overflow if an input line is 2^31 characters long, or
more; a better fix would be to check for overflow before incrementing
cur_col, in various places in the main input loop.

Reply via email to