diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-16 13:45:13 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2014-10-16 13:45:13 +0000 |
commit | 192e6b5499cb112c239efb9917467966c070063c (patch) | |
tree | 194cd368803fe683af62a39e6a32a3ed984d5b69 /usr.bin/col/col.c | |
parent | b7f6053c1a864281cc576b5acae2e06b34385321 (diff) |
1) Fix a segfault triggered by an input line containing two consecutive
backspace characters beyond column MAX_SHRT, overflowing c_column.
2) Fix imcomplete initialization of the final element of the *count
array by adding a missing pair of parentheses.
3) For code clarity and extra safety, change all variables dealing
with column numbers from int to size_t such that they cannot overflow.
Found while reviewing the patch from deraadt@'s reallocarray() rampage.
Feedback and OK millert@.
Diffstat (limited to 'usr.bin/col/col.c')
-rw-r--r-- | usr.bin/col/col.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/usr.bin/col/col.c b/usr.bin/col/col.c index 2030ed1d395..26410064d5f 100644 --- a/usr.bin/col/col.c +++ b/usr.bin/col/col.c @@ -1,4 +1,4 @@ -/* $OpenBSD: col.c,v 1.12 2014/10/08 19:59:58 deraadt Exp $ */ +/* $OpenBSD: col.c,v 1.13 2014/10/16 13:45:12 schwarze Exp $ */ /* $NetBSD: col.c,v 1.7 1995/09/02 05:48:50 jtc Exp $ */ /*- @@ -62,7 +62,7 @@ typedef char CSET; typedef struct char_str { #define CS_NORMAL 1 #define CS_ALTERNATE 2 - short c_column; /* column character is in */ + size_t c_column; /* column character is in */ CSET c_set; /* character set (currently only 2) */ char c_char; /* character in question */ } CHAR; @@ -72,10 +72,10 @@ struct line_str { CHAR *l_line; /* characters on the line */ LINE *l_prev; /* previous line */ LINE *l_next; /* next line */ - int l_lsize; /* allocated sizeof l_line */ - int l_line_len; /* strlen(l_line) */ + size_t l_lsize; /* allocated sizeof l_line */ + size_t l_line_len; /* strlen(l_line) */ + size_t l_max_col; /* max column in the line */ int l_needs_sort; /* set if chars went in out of order */ - int l_max_col; /* max column in the line */ }; LINE *alloc_line(void); @@ -107,7 +107,7 @@ main(int argc, char *argv[]) CSET cur_set; /* current character set */ LINE *l; /* current line */ int extra_lines; /* # of lines above first line */ - int cur_col; /* current column */ + size_t cur_col; /* current column */ int cur_line; /* line number of current position */ int max_line; /* max value of cur_line */ int this_line; /* line l points to */ @@ -148,7 +148,8 @@ main(int argc, char *argv[]) /* this value is in half lines */ max_bufd_lines *= 2; - adjust = cur_col = extra_lines = warned = 0; + adjust = extra_lines = warned = 0; + cur_col = 0; cur_line = max_line = nflushd_lines = this_line = 0; cur_set = last_set = CS_NORMAL; lines = l = alloc_line(); @@ -261,7 +262,7 @@ main(int argc, char *argv[]) } /* grow line's buffer? */ if (l->l_line_len + 1 >= l->l_lsize) { - int need; + size_t need; need = l->l_lsize ? l->l_lsize : 45; l->l_line = xreallocarray(l->l_line, @@ -364,14 +365,15 @@ void flush_line(LINE *l) { CHAR *c, *endc; - int nchars, last_col, this_col; + size_t nchars, last_col, this_col; last_col = 0; nchars = l->l_line_len; if (l->l_needs_sort) { static CHAR *sorted; - static int count_size, *count, i, save, sorted_size, tot; + static size_t count_size, i, sorted_size; + static int *count, save, tot; /* * Do an O(n) sort on l->l_line by column being careful to @@ -387,8 +389,8 @@ flush_line(LINE *l) count = xreallocarray(count, count_size, sizeof(int)); } - memset((char *)count, 0, sizeof(int) * l->l_max_col + 1); - for (i = nchars, c = l->l_line; --i >= 0; c++) + memset(count, 0, sizeof(*count) * (l->l_max_col + 1)); + for (i = nchars, c = l->l_line; i-- > 0; c++) count[c->c_column]++; /* @@ -401,7 +403,7 @@ flush_line(LINE *l) tot += save; } - for (i = nchars, c = l->l_line; --i >= 0; c++) + for (i = nchars, c = l->l_line; i-- > 0; c++) sorted[count[c->c_column]++] = *c; c = sorted; } else @@ -418,19 +420,19 @@ flush_line(LINE *l) c = endc - 1; if (this_col > last_col) { - int nspace = this_col - last_col; + size_t nspace = this_col - last_col; if (compress_spaces && nspace > 1) { - int ntabs; + size_t ntabs; ntabs = ((last_col % 8) + nspace) / 8; if (ntabs) { nspace -= (ntabs * 8) - (last_col % 8); - while (--ntabs >= 0) + while (ntabs-- > 0) PUTC('\t'); } } - while (--nspace >= 0) + while (nspace-- > 0) PUTC(' '); last_col = this_col; } |