diff options
author | Christian Neukirchen <chneukirchen@gmail.com> | 2015-11-14 17:00:40 +0100 |
---|---|---|
committer | Christian Neukirchen <chneukirchen@gmail.com> | 2015-11-14 17:00:40 +0100 |
commit | c192827dc2c6163bdae3cc8642bea4c9bffc760a (patch) | |
tree | 1f4ae24cdff356351086ca9dcfd5e25ee75c1131 | |
parent | 630132a6435f55963747d4f1f2e26b80eb795484 (diff) | |
download | arr-c192827dc2c6163bdae3cc8642bea4c9bffc760a.tar.gz arr-c192827dc2c6163bdae3cc8642bea4c9bffc760a.tar.xz arr-c192827dc2c6163bdae3cc8642bea4c9bffc760a.zip |
Check all bounds
-rw-r--r-- | arr.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/arr.c b/arr.c index 2644cf3..b489720 100644 --- a/arr.c +++ b/arr.c @@ -22,7 +22,7 @@ static char *s; // "%{" FIELD (CHOP FIELD)* (("|" | "*") FIELD ((, | :) FIELD)*)? "}" void -fmt_range(char **args, int bytewise) +fmt_range(char **args, int bytewise, size_t argsnum) { long n = 0; char *end; @@ -42,11 +42,13 @@ fmt_range(char **args, int bytewise) } s = end; if (bytewise) { - printf("%c", args[0][n-1]); + if (n <= argsnum) + printf("%c", args[0][n-1]); } else { if (printed++) printf("%c", lastsplit); - printf("%s", args[n]); + if (n < argsnum) + printf("%s", args[n]); } break; case ',': @@ -62,8 +64,12 @@ fmt_range(char **args, int bytewise) fprintf(stderr, "can't parse number at '%s'.\n", s); exit(1); } + if (s == end) // default to max range + n = argsnum; s = end; if (bytewise) { + if (n > argsnum) + n = argsnum; if (l <= n) for (l++; l <= n; l++) printf("%c", args[0][l-1]); @@ -71,6 +77,8 @@ fmt_range(char **args, int bytewise) for (l--; l >= n; l--) printf("%c", args[0][l-1]); } else { + if (n >= argsnum) + n = argsnum-1; if (l <= n) for (l++; l <= n; l++) { if (printed++) @@ -97,7 +105,7 @@ fmt_range(char **args, int bytewise) } void -fmt_inner(char **args) +fmt_inner(char **args, size_t argsnum) { long field, newfield; char *end; @@ -123,17 +131,19 @@ fmt_inner(char **args) break; case '|': s++; - fmt_range(args, 0); + fmt_range(args, 0, argsnum); return; case '*': s++; - fmt_range(args+field, 1); + if (field >= 0 && field < argsnum-1) + fmt_range(args+field, 1, strlen(args[field])); + else + fmt_range(args, 1, 0); return; case '}': s++; - if (field == 0) - abort(); - printf("%s", args[field]); + if (field >= 1 && field < argsnum-1) + printf("%s", args[field]); return; case '"': s++; @@ -154,7 +164,11 @@ fmt_inner(char **args) lastsplit = *s; s++; split2:; - char *t = strdup(args[field]); + char *t; + if (field >= 1 && field < argsnum-1) + t = strdup(args[field]); + else + t = strdup(""); char **newargs = calloc(32 /*XXX*/, sizeof (char *)); if (lastsplit == ' ') { // split on any ws while (isspace((unsigned char)*t)) @@ -177,6 +191,7 @@ fmt_inner(char **args) } } args = newargs; + argsnum = i; field = 0; } } @@ -184,7 +199,7 @@ fmt_inner(char **args) } void -fmt(const char *pattern, char **args) +fmt(const char *pattern, char **args, size_t argsnum) { s = pattern; lastsplit = '\t'; @@ -200,7 +215,7 @@ fmt(const char *pattern, char **args) break; case '{': s++; - fmt_inner(args); + fmt_inner(args, argsnum); break; default: putchar('%'); @@ -283,7 +298,7 @@ main(int argc, char *argv[]) { } if (eof) break; - fmt(argv[1], lines); + fmt(argv[1], lines, argc+stdins); printf("%c", delim); } |