Date: Wed, 09 May 2001 14:04:32 -0700 From: Dima Dorfman <dima@unixfreak.org> To: audit@freebsd.org Subject: jot(1) patch Message-ID: <20010509210433.1BDA13E28@bazooka.unixfreak.org>
next in thread | raw e-mail | index | archive | help
The attached patch fixes some overflows in jot(1) and syncs up to OpenBSD a little. Significant changes include: - use getopt - de-register - fix overflows in -b and -w options; old behavior: dima@hornet% jot -b `perl -e 'print "A" x 2000'` 5 Segmentation fault (core dumped) dima@hornet% jot -w `perl -e 'print "A" x 2000'` 5 Segmentation fault (core dumped) (this is my primary motivation for the patch) - use strlcpy and snprintf - check return values of the above - fix other gratuituos diffs to OpenBSD; not a complete sync, but better than nothing Please review. Thanks, Dima Dorfman dima@unixfreak.org Index: jot.c =================================================================== RCS file: /st/src/FreeBSD/src/usr.bin/jot/jot.c,v retrieving revision 1.14 diff -u -r1.14 jot.c --- jot.c 2000/07/10 05:57:29 1.14 +++ jot.c 2001/05/09 20:58:25 @@ -51,8 +51,8 @@ * Author: John Kunze, Office of Comp. Affairs, UCB */ -#include <ctype.h> #include <err.h> +#include <ctype.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> @@ -65,7 +65,7 @@ #define ENDER_DEF 100 #define STEP_DEF 1 -#define isdefault(s) (strcmp((s), "-") == 0) +#define is_default(s) (strcmp((s), "-") == 0) double begin; double ender; @@ -83,11 +83,10 @@ char *sepstring = "\n"; char format[BUFSIZ]; -void getargs __P((int, char *[])); -void getformat __P((void)); +void getformat __P((void)); int getprec __P((char *)); -int putdata __P((double, long)); -static void usage __P((void)); +int putdata __P((double, long)); +static void usage __P((void)); int main(argc, argv) @@ -96,37 +95,15 @@ { double xd, yd; long id; - register double *x = &xd; - register double *y = &yd; - register long *i = &id; - - getargs(argc, argv); - if (randomize) { - *x = (ender - begin) * (ender > begin ? 1 : -1); - for (*i = 1; *i <= reps || infinity; (*i)++) { - *y = (double) arc4random() / ULONG_MAX; - if (putdata(*y * *x + begin, reps - *i)) - errx(1, "range error in conversion"); - } - } else - for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s) - if (putdata(*x, reps - *i)) - errx(1, "range error in conversion"); - if (!nofinalnl) - putchar('\n'); - exit(0); -} - -void -getargs(ac, av) - int ac; - char *av[]; -{ - register unsigned int mask = 0; - register int n = 0; + double *x = &xd; + double *y = &yd; + long *i = &id; + unsigned int mask = 0; + int n = 0; + int ch; - while (--ac && **++av == '-' && !isdefault(*av)) - switch ((*av)[1]) { + while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1) + switch ((char)ch) { case 'r': randomize = 1; break; @@ -138,72 +115,63 @@ break; case 'b': boring = 1; + /* FALLTHROUGH */ case 'w': - if ((*av)[2]) - strcpy(format, *av + 2); - else if (!--ac) - errx(1, "need context word after -w or -b"); - else - strcpy(format, *++av); + if (strlcpy(format, optarg, sizeof(format)) >= + sizeof(format)) + errx(1, "-%c word too long", ch); break; case 's': - if ((*av)[2]) - sepstring = *av + 2; - else if (!--ac) - errx(1, "need string after -s"); - else - sepstring = *++av; + sepstring = optarg; break; case 'p': - if ((*av)[2]) - prec = atoi(*av + 2); - else if (!--ac) - errx(1, "need number after -p"); - else - prec = atoi(*++av); + prec = atoi(optarg); if (prec <= 0) errx(1, "bad precision value"); break; default: usage(); } + argc -= optind; + argv += optind; - switch (ac) { /* examine args right to left, falling thru cases */ + switch (argc) { /* examine args right to left, falling thru cases */ case 4: - if (!isdefault(av[3])) { - if (!sscanf(av[3], "%lf", &s)) - errx(1, "bad s value: %s", av[3]); + if (!is_default(argv[3])) { + if (!sscanf(argv[3], "%lf", &s)) + errx(1, "bad s value: %s", argv[3]); mask |= 01; } case 3: - if (!isdefault(av[2])) { - if (!sscanf(av[2], "%lf", &ender)) - ender = av[2][strlen(av[2])-1]; + if (!is_default(argv[2])) { + if (!sscanf(argv[2], "%lf", &ender)) + ender = argv[2][strlen(argv[2])-1]; mask |= 02; if (!prec) - n = getprec(av[2]); + n = getprec(argv[2]); } case 2: - if (!isdefault(av[1])) { - if (!sscanf(av[1], "%lf", &begin)) - begin = av[1][strlen(av[1])-1]; + if (!is_default(argv[1])) { + if (!sscanf(argv[1], "%lf", &begin)) + begin = argv[1][strlen(argv[1])-1]; mask |= 04; if (!prec) - prec = getprec(av[1]); + prec = getprec(argv[1]); if (n > prec) /* maximum precision */ prec = n; } case 1: - if (!isdefault(av[0])) { - if (!sscanf(av[0], "%ld", &reps)) - errx(1, "bad reps value: %s", av[0]); + if (!is_default(argv[0])) { + if (!sscanf(argv[0], "%ld", &reps)) + errx(1, "bad reps value: %s", argv[0]); mask |= 010; } break; case 0: usage(); default: - errx(1, "too many arguments. What do you mean by %s?", av[4]); + errx(1, "too many arguments. What do you mean by %s?", + argv[4]); } getformat(); while (mask) /* 4 bit mask has 1's where last 4 args were given */ @@ -257,7 +225,7 @@ mask = 015; break; case 012: - s = (randomize ? -1.0 : STEP_DEF); + s = (randomize ? time(NULL) : STEP_DEF); mask = 013; break; case 013: @@ -265,8 +233,7 @@ begin = BEGIN_DEF; else if (reps == 0) errx(1, "must specify begin if reps == 0"); - else - begin = ender - reps * s + s; + begin = ender - reps * s + s; mask = 0; break; case 014: @@ -306,6 +273,20 @@ } if (reps == 0) infinity = 1; + if (randomize) { + *x = (ender - begin) * (ender > begin ? 1 : -1); + for (*i = 1; *i <= reps || infinity; (*i)++) { + *y = (double) arc4random() / ULONG_MAX; + if (putdata(*y * *x + begin, reps - *i)) + errx(1, "range error in conversion"); + } + } else + for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s) + if (putdata(*x, reps - *i)) + errx(1, "range error in conversion"); + if (!nofinalnl) + putchar('\n'); + exit(0); } int @@ -346,7 +327,7 @@ } static void -usage() +usage(void) { fprintf(stderr, "%s\n%s\n", "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]", @@ -358,8 +339,8 @@ getprec(s) char *s; { - register char *p; - register char *q; + char *p; + char *q; for (p = s; *p; p++) if (*p == '.') @@ -375,8 +356,9 @@ void getformat() { - register char *p; + char *p; int dot, hash, space, sign, numbers = 0; + size_t sz; char *s; if (boring) /* no need to bother */ @@ -384,14 +366,19 @@ for (p = format; *p; p++) /* look for '%' */ if (*p == '%' && *(p+1) != '%') /* leave %% alone */ break; - if (!*p && !chardata) - sprintf(p, "%%.%df", prec); - else if (!*p && chardata) { - strcpy(p, "%c"); + sz = sizeof(format) - strlen(format) - 1; + if (!*p && !chardata) { + if (snprintf(p, sz, "%%.%df", prec) >= (int)sz) + errx(1, "-w word too long"); + } else if (!*p && chardata) { + if (strlcpy(p, "%c", sz) >= sz) + errx(1, "-w word too long"); intdata = 1; - } else if (!*(p+1)) + } else if (!*(p+1)) { + if (sz <= 0) + errx(1, "-w word too long"); strcat(format, "%"); /* cannot end in single '%' */ - else { + } else { /* * Allow conversion format specifiers of the form * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010509210433.1BDA13E28>