Hello list!
While looking at the code of usr.bin/fold i noticed that the way
it parses arguments for the (obsolete) -number syntax suffers from an
it loops over each digit in a -xxxxx stream of numbers from right to left
and sets a counter = (counter * 10) + (x - '0').
Then it checks for counter > (INT_MAX / 10)
integer overflow:
$fold -2147483648 foo
fold: illegal width value, too small
this is MAX_INT on my platform. the way it parses it will produce the
same error if you keep adding digits after the end (since it never gets
to read them) but it will correctly catch the large number error if you
increase any nonlast digits. Looking around i noticed how head.c handles
the -number case and it seems way better so i implemented that in fold.
other programs might suffer from this funky logic in our base like grep.
imo if we want to keep this looping over the digits each time * 10
+ (ch - '0') , then it could be better to just check for < 0 to get
the overflow (right?). But in any case i think that leaving the erroring
for strtonum is better.
Index: fold.c
===================================================================
RCS file: /cvs/src/usr.bin/fold/fold.c,v
retrieving revision 1.13
diff -u -p -r1.13 fold.c
--- fold.c 22 Oct 2010 14:11:22 -0000 1.13
+++ fold.c 22 Oct 2013 02:57:34 -0000
@@ -54,12 +54,20 @@ main(int argc, char *argv[])
{
int ch, lastch, newarg, prevoptind, width;
const char *errstr;
+ char *p = NULL;
width = 0;
lastch = '\0';
prevoptind = 1;
newarg = 1;
- while ((ch = getopt(argc, argv, "0123456789bsw:")) != -1) {
+ /* handle obsolete -number syntax */
+ if (argc > 1 && argv[1][0] == '-' && isdigit(argv[1][1])) {
+ p = argv[1] + 1;
+ argc--;
+ argv++;
+ }
+
+ while ((ch = getopt(argc, argv, "bsw:")) != -1) {
switch (ch) {
case 'b':
count_bytes = 1;
@@ -73,18 +81,6 @@ main(int argc, char *argv[])
errx(1, "illegal width value, %s: %s", errstr,
optarg);
break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (newarg)
- width = 0;
- else if (!isdigit(lastch))
- usage();
- if (width > INT_MAX / 10)
- errx(1, "illegal width value, too large");
- width = (width * 10) + (ch - '0');
- if (width < 1)
- errx(1, "illegal width value, too small");
- break;
default:
usage();
}
@@ -94,6 +90,12 @@ main(int argc, char *argv[])
}
argv += optind;
argc -= optind;
+
+ if (p) {
+ width = strtonum(p, 1, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "illegal width value %s: %s", errstr, p);
+ }
if (width == 0)
width = DEFLINEWIDTH;
[demime 1.01d removed an attachment of type application/pgp-signature]