Mercurial > illumos > illumos-gate
changeset 3774:9e3b03d406cc
6508815 *col* dumps core on stdin fuzz testing
author | as145665 |
---|---|
date | Wed, 07 Mar 2007 11:21:49 -0800 |
parents | 19ce51f14e6a |
children | 3617a86b0236 |
files | usr/src/cmd/col/col.c |
diffstat | 1 files changed, 107 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/col/col.c Wed Mar 07 09:58:36 2007 -0800 +++ b/usr/src/cmd/col/col.c Wed Mar 07 11:21:49 2007 -0800 @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,9 +18,10 @@ * * CDDL HEADER END */ + /* - * Copyright (c) 1998, 2001 by Sun Microsystems, Inc. - * All Rights Reserved + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -52,6 +52,7 @@ wchar_t *page[PL]; wchar_t lbuff[LINELN], *line; +wchar_t *lbuffend = lbuff + LINELN - 1; wchar_t ws_blank[2] = {' ', 0}; char esc_chars, underline, temp_off, smart; int bflag, xflag, fflag, pflag; @@ -71,6 +72,7 @@ static void incr(void); static void decr(void); static void wsinsert(wchar_t *, int); +static void incr_line(int); static int wcscrwidth(wchar_t); int @@ -131,8 +133,11 @@ while ((c = getwchar()) != EOF) { if (underline && temp_off && c > ' ') { outc(ESC); - if (*line) line++; - *line++ = 'X'; + if (*line) { + incr_line(1); + } + *line = 'X'; + incr_line(1); *line = temp_off = '\0'; } if (c != '\b') @@ -142,9 +147,11 @@ case '\n': if (underline && !temp_off) { if (*line) - line++; - *line++ = ESC; - *line++ = 'Y'; + incr_line(1); + *line = ESC; + incr_line(1); + *line = 'Y'; + incr_line(1); *line = '\0'; temp_off = '1'; } @@ -191,15 +198,15 @@ default: if (pflag) { /* pass through esc */ outc(ESC); - line++; + incr_line(1); *line = c; - line++; + incr_line(1); *line = '\0'; esc_chars = 1; if (c == 'X') underline = 1; if (c == 'Y' && underline) - underline = temp_off = '\0'; + underline = temp_off = '\0'; if (c == ']') smart = 1; if (c == '[') @@ -233,7 +240,8 @@ case '\b': if (esc_chars) { - *line++ = '\b'; + *line = '\b'; + incr_line(1); *line = '\0'; } else if (cp > 0) cp--; @@ -305,7 +313,7 @@ esc_chars = '\0'; switch (*line) { case ESC: - line++; + incr_line(1); esc_chars = 1; break; case '\0': @@ -319,7 +327,7 @@ default: lp += wcscrwidth(*line); } - line++; + incr_line(1); } while (*line == '\b') { /* @@ -328,19 +336,20 @@ * represents a two-column character, and a backspace * always goes back by one column.) */ - for (n = 0; *line == '\b'; line++) { + for (n = 0; *line == '\b'; incr_line(1)) { n++; lp--; } while (n > 0 && lp < cp) { - i = *line++; + i = *line; + incr_line(1); i = wcscrwidth(i); n -= i; lp += i; } } while (*line == ESC) - line += 6; + incr_line(6); widthc = wcscrwidth(c); widthl = wcscrwidth(*line); if (bflag || (*line == '\0') || *line == ' ') { @@ -349,37 +358,61 @@ } else if (widthl > widthc) { n = widthl - widthc; wsinsert(line, n); - *line++ = c; - for (i = 0; i < n; i++) - *line++ = ' '; + *line = c; + incr_line(1); + for (i = 0; i < n; i++) { + *line = ' '; + incr_line(1); + } line = lbuff; lp = 0; } else { n = widthc - widthl; - for (p1 = line+1; n > 0; n -= wcscrwidth(i)) - i = *p1++; - *line = c; - (void) wcscpy(line+1, p1); - + if (line < lbuffend) { + for (p1 = line+1; n > 0 && p1 < lbuffend; + n -= wcscrwidth(i)) { + i = *p1++; + } + *line = c; + if (p1 < lbuffend) { + (void) wcscpy(line+1, p1); + } else { + (void) fprintf(stderr, + gettext("col: Line too long.\n")); + exit(1); + } + } else { + (void) fprintf(stderr, + gettext("col: Line too long.\n")); + exit(1); + } } } else { if (smart && (widthl == 1) && (widthc == 1)) { wchar_t c1, c2, c3, c4, c5, c6, c7; - c1 = *++line; - *line++ = ESC; + incr_line(1); + c1 = *line; + *line = ESC; + incr_line(1); c2 = *line; - *line++ = '['; + *line = '['; + incr_line(1); c3 = *line; - *line++ = '\b'; + *line = '\b'; + incr_line(1); c4 = *line; - *line++ = ESC; + *line = ESC; + incr_line(1); c5 = *line; - *line++ = ']'; + *line = ']'; + incr_line(1); c6 = *line; - *line++ = c; + *line = c; + incr_line(1); while (c1) { c7 = *line; - *line++ = c1; + *line = c1; + incr_line(1); c1 = c2; c2 = c3; c3 = c4; @@ -390,26 +423,37 @@ } else { if ((widthl == 1) && (widthc == 1)) { wchar_t c1, c2, c3; - c1 = *++line; - *line++ = '\b'; + incr_line(1); + c1 = *line; + *line = '\b'; + incr_line(1); c2 = *line; - *line++ = c; + *line = c; + incr_line(1); while (c1) { c3 = *line; - *line++ = c1; + *line = c1; + incr_line(1); c1 = c2; c2 = c3; } } else { width = (widthc > widthl) ? widthc : widthl; - for (i = 0; i < width; i += wcscrwidth(c1)) - c1 = *line++; + for (i = 0; i < width; i += wcscrwidth(c1)) { + c1 = *line; + incr_line(1); + } wsinsert(line, width + (width - widthc + 1)); - for (i = 0; i < width; i++) - *line++ = '\b'; - *line++ = c; - for (i = widthc; i < width; i++) - *line++ = ' '; + for (i = 0; i < width; i++) { + *line = '\b'; + incr_line(1); + } + *line = c; + incr_line(1); + for (i = widthc; i < width; i++) { + *line = ' '; + incr_line(1); + } } } lp = 0; @@ -568,6 +612,23 @@ *p2-- = *p1--; } +/* + * incr_line - increments line pointer and checks for array out of bounds + * amt: assumed to be >= 1 + * exit on error to avoid line pointer accessing out of the array + */ +static void +incr_line(int amt) +{ + if (line < lbuffend - amt + 1) { + line += amt; + } else { + (void) fprintf(stderr, gettext("col: Line too long.\n")); + exit(1); + } +} + + static int wcscrwidth(wchar_t wc) {