From owner-freebsd-bugs Sun May 20 16:50:24 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id AD13337B43C for ; Sun, 20 May 2001 16:50:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.1/8.11.1) id f4KNo1j94780; Sun, 20 May 2001 16:50:01 -0700 (PDT) (envelope-from gnats) Received: from bazooka.unixfreak.org (bazooka.unixfreak.org [63.198.170.138]) by hub.freebsd.org (Postfix) with ESMTP id 2445237B42C for ; Sun, 20 May 2001 16:48:03 -0700 (PDT) (envelope-from dima@unixfreak.org) Received: from spike.unixfreak.org (spike [63.198.170.139]) by bazooka.unixfreak.org (Postfix) with ESMTP id CF9E23E0B for ; Sun, 20 May 2001 16:48:02 -0700 (PDT) Received: (from dima@localhost) by spike.unixfreak.org (8.11.3/8.11.1) id f4KNm2801666; Sun, 20 May 2001 16:48:02 -0700 (PDT) (envelope-from dima) Message-Id: <200105202348.f4KNm2801666@spike.unixfreak.org> Date: Sun, 20 May 2001 16:48:02 -0700 (PDT) From: dd@freebsd.org Reply-To: dd@freebsd.org To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.113 Subject: bin/27480: [PATCH] fixes to jot(1) from OpenBSD Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 27480 >Category: bin >Synopsis: [PATCH] fixes to jot(1) from OpenBSD >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun May 20 16:50:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Dima Dorfman >Release: FreeBSD 5.0-20010519-CURRENT i386 >Organization: Private >Environment: System: FreeBSD spike.unixfreak.org 5.0-20010519-CURRENT FreeBSD 5.0-20010519-CURRENT #4: Sun May 20 14:16:15 PDT 2001 dima@spike.unixfreak.org:/c/home/dima/w/f/c/sys/compile/SPIKE i386 >Description: 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 >How-To-Repeat: 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) >Fix: I've sent this to -audit; it elicited comments about breaking K&R, which I addressed, but no solid reviews. 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/14 07:18:20 @@ -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; + double *x = &xd; + double *y = &yd; + long *i = &id; + unsigned int mask = 0; + int n = 0; + int ch; - 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; - - 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 @@ -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 >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message