summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2014-10-16 13:45:13 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2014-10-16 13:45:13 +0000
commit192e6b5499cb112c239efb9917467966c070063c (patch)
tree194cd368803fe683af62a39e6a32a3ed984d5b69
parentb7f6053c1a864281cc576b5acae2e06b34385321 (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@.
-rw-r--r--usr.bin/col/col.c36
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;
}