diff options
author | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2010-11-06 17:48:46 +0000 |
---|---|---|
committer | Jean-Sébastien Pédron <dumbbell@FreeBSD.org> | 2010-11-06 17:48:46 +0000 |
commit | 76423301d361678d6a8ded370814bad1c3b00421 (patch) | |
tree | 0b01586ecbae09c5376a3e58f3ddc8f788572d55 /usr.bin/fold/fold.c | |
parent | 9283118f01acfe5ca731db462d9df23fe0b794f8 (diff) | |
download | src-76423301d361678d6a8ded370814bad1c3b00421.tar.gz src-76423301d361678d6a8ded370814bad1c3b00421.zip |
Fix a segmentation fault in argument processing.
The crash was caused by a command line such as this one:
# foldl -b1
PR: bin/151592
Reported by: Marcus Reid <marcus@blazingdot.com>
Tested by: Marcus Reid <marcus@blazingdot.com>
MFC after: 3 days
Notes
Notes:
svn path=/head/; revision=214893
Diffstat (limited to 'usr.bin/fold/fold.c')
-rw-r--r-- | usr.bin/fold/fold.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/usr.bin/fold/fold.c b/usr.bin/fold/fold.c index 59d8fc59adfd..d4255fc70ebd 100644 --- a/usr.bin/fold/fold.c +++ b/usr.bin/fold/fold.c @@ -71,14 +71,14 @@ int sflag; /* Split on word boundaries */ int main(int argc, char **argv) { - int ch; + int ch, previous_ch; int rval, width; - char *p; (void) setlocale(LC_CTYPE, ""); width = -1; - while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) + previous_ch = 0; + while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) { switch (ch) { case 'b': bflag = 1; @@ -93,17 +93,33 @@ main(int argc, char **argv) break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - if (width == -1) { - p = argv[optind - 1]; - if (p[0] == '-' && p[1] == ch && !p[2]) - width = atoi(++p); - else - width = atoi(argv[optind] + 1); + /* Accept a width as eg. -30. Note that a width + * specified using the -w option is always used prior + * to this undocumented option. */ + switch (previous_ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* The width is a number with multiple digits: + * add the last one. */ + width = width * 10 + (ch - '0'); + break; + default: + /* Set the width, unless it was previously + * set. For instance, the following options + * would all give a width of 5 and not 10: + * -10 -w5 + * -5b10 + * -5 -10b */ + if (width == -1) + width = ch - '0'; + break; } break; default: usage(); } + previous_ch = ch; + } argv += optind; argc -= optind; |