From owner-freebsd-bugs Mon Dec 13 13: 0:19 1999 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id C49C9151BE for ; Mon, 13 Dec 1999 13:00:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id NAA25142; Mon, 13 Dec 1999 13:00:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from troutmask.apl.washington.edu (troutmask.apl.washington.edu [128.95.76.54]) by hub.freebsd.org (Postfix) with ESMTP id 994FF15266 for ; Mon, 13 Dec 1999 12:51:09 -0800 (PST) (envelope-from kargl@troutmask.apl.washington.edu) Received: (from kargl@localhost) by troutmask.apl.washington.edu (8.9.3/8.9.3) id MAA89742; Mon, 13 Dec 1999 12:50:24 -0800 (PST) (envelope-from kargl) Message-Id: <199912132050.MAA89742@troutmask.apl.washington.edu> Date: Mon, 13 Dec 1999 12:50:24 -0800 (PST) From: "Steven G. Kargl" Reply-To: kargl@troutmask.apl.washington.edu To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: bin/15471: fsplit buffer overflow fixes Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >Number: 15471 >Category: bin >Synopsis: Fix several buffer overflows >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Dec 13 13:00:02 PST 1999 >Closed-Date: >Last-Modified: >Originator: Steven G. Kargl >Release: FreeBSD 4.0-CURRENT i386 >Organization: apl/uw >Environment: All version of FreeBSD. >Description: fsplit(1) has several buffer overflow problems. These overflows could be exploited by a user on a system to cause problems (either to breach security or panic a system). >How-To-Repeat: There are at least three ways to over flow buffers: 1. fsplit -e arg1 ... -e arg100 -e START_OF_OVERFLOW prog.f 2. fsplit -e arg_containing_more_1000_chars prog.f 3. fsplit prog.f where prog.f contains a Fortran subprogram with a name containing more than 20 chars: program ThisNameIsTooLongForTheBuffer end >Fix: The attached patch does: * Remove the custom command line parser. Use getopt(3), instead. Fixes 1 and 2 above. * Use dynamic memory allocation to remove static buffers. Fixes 1 and 2 above. * Keep track of characters copied from subprogram names in scan_name(). Fixes 3 above. * Give fsplit a "return 0;" statement * Include to properly prototype exit(3). * Whitespace clean up * Update man page. fsplit(1) works with Fortran 77 and older code. diff -u -r /usr/src/usr.bin/fsplit/fsplit.1 fsplit/fsplit.1 --- /usr/src/usr.bin/fsplit/fsplit.1 Mon Aug 30 08:00:49 1999 +++ fsplit/fsplit.1 Mon Dec 13 12:25:49 1999 @@ -39,7 +39,7 @@ .Os BSD 4.2 .Sh NAME .Nm fsplit -.Nd split a multi-routine Fortran file into individual files +.Nd split a multi-routine Fortran 77 file into individual files .Sh SYNOPSIS .Nm fsplit .Op Fl e Ar efile @@ -47,8 +47,8 @@ .Op Ar file .Sh DESCRIPTION .Nm Fsplit -takes as input either a file or standard input containing Fortran source code. -It attempts to split the input into separate routine files of the +takes as input either a file or standard input containing Fortran 77 source +code. It attempts to split the input into separate routine files of the form .Ar name.f , where @@ -104,3 +104,7 @@ .Fl e for unnamed main programs and block data subprograms since you must predict the created file name. +.Pp +.Nm +can be used with Fortran 77 and older source code. It understands neither +Fortran 90/95 syntax nor free form source files. diff -u -r /usr/src/usr.bin/fsplit/fsplit.c fsplit/fsplit.c --- /usr/src/usr.bin/fsplit/fsplit.c Tue Sep 7 11:59:34 1999 +++ fsplit/fsplit.c Mon Dec 13 12:14:36 1999 @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -90,11 +91,9 @@ #define TRUE 1 #define FALSE 0 -int extr = FALSE, - extrknt = -1, - extrfnd[100]; -char extrbuf[1000], - *extrnames[100]; + +int extr = FALSE, extrknt = -1, *extrfnd; +char **extrnames; struct stat sbuf; #define trim(p) while (*p == ' ' || *p == '\t') p++ @@ -103,101 +102,119 @@ void get_name __P((char *, int)); char *functs __P((char *)); int lend __P((void)); -int lname __P((char *)); +int lname __P((char *, int)); char *look __P((char *, char *)); int saveit __P((char *)); -int scan_name __P((char *, char *)); +int scan_name __P((char *, char *, int)); char *skiplab __P((char *)); static void usage __P((void)); int main(argc, argv) +int argc; char **argv; { + extern int optind; + extern char *optarg; + register FILE *ofp; /* output file */ register int rv; /* 1 if got card in output file, 0 otherwise */ register char *ptr; int nflag, /* 1 if got name of subprog., 0 otherwise */ retval, i; - char name[20], - *extrptr = extrbuf; + char name[20]; - /* scan -e options */ - while ( argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e') { + if (argc > 2) { extr = TRUE; - ptr = argv[1] + 2; - if(!*ptr) { - argc--; - argv++; - if(argc <= 1) + + extrfnd = (int *) malloc(argc * sizeof(int)); + if (extrfnd == NULL) + errx(1, NULL); + + extrnames = (char **) malloc(argc * sizeof(char *)); + if (extrnames == NULL) + errx(1, NULL); + + while ((i = getopt(argc, argv, "e:")) != -1) { + switch (i) { + case 'e': + extrknt++; + extrfnd[extrknt] = FALSE; + extrnames[extrknt] = optarg; + break; + default: usage(); - ptr = argv[1]; + } } - extrknt = extrknt + 1; - extrnames[extrknt] = extrptr; - extrfnd[extrknt] = FALSE; - while(*ptr) *extrptr++ = *ptr++; - *extrptr++ = 0; + + argc -= optind; + argv += optind; + } else { argc--; argv++; } - if (argc > 2) + if (argc > 1) usage(); - else if (argc == 2) { - if ((ifp = fopen(argv[1], "r")) == NULL) + else if (argc == 1) { + if ((ifp = fopen(*argv, "r")) == NULL) errx(1, "cannot open %s", argv[1]); } else ifp = stdin; - for(;;) { - /* look for a temp file that doesn't correspond to an existing file */ - get_name(x, 3); - ofp = fopen(x, "w"); - nflag = 0; - rv = 0; - while (getline() > 0) { - rv = 1; - fprintf(ofp, "%s", buf); - if (lend()) /* look for an 'end' statement */ - break; - if (nflag == 0) /* if no name yet, try and find one */ - nflag = lname(name); - } - fclose(ofp); - if (rv == 0) { /* no lines in file, forget the file */ - unlink(x); - retval = 0; - for ( i = 0; i <= extrknt; i++ ) - if(!extrfnd[i]) { - retval = 1; - warnx("%s not found", extrnames[i]); - } - exit( retval ); - } - if (nflag) { /* rename the file */ - if(saveit(name)) { - if (stat(name, &sbuf) < 0 ) { - link(x, name); - unlink(x); - printf("%s\n", name); + + for (;;) { + /* look for a temp file that doesn't correspond to an existing file */ + get_name(x, 3); + ofp = fopen(x, "w"); + if (ofp == NULL) + errx(1, "can not open %s", x); + nflag = 0; + rv = 0; + while (getline() > 0) { + rv = 1; + fprintf(ofp, "%s", buf); + if (lend()) /* look for an 'end' statement */ + break; + if (nflag == 0) /* if no name yet, try and find one */ + nflag = lname(name, 20); + } + fclose(ofp); + if (rv == 0) { /* no lines in file, forget the file */ + unlink(x); + retval = 0; + for ( i = 0; i <= extrknt; i++ ) + if(!extrfnd[i]) { + retval = 1; + warnx("%s not found", extrnames[i]); + } + exit( retval ); + } + if (nflag) { /* rename the file */ + if(saveit(name)) { + if (stat(name, &sbuf) < 0 ) { + link(x, name); + unlink(x); + printf("%s\n", name); + continue; + } else if (strcmp(name, x) == 0) { + printf("%s\n", x); + continue; + } + printf("%s already exists, put in %s\n", name, x); continue; - } else if (strcmp(name, x) == 0) { - printf("%s\n", x); + } else + unlink(x); continue; - } - printf("%s already exists, put in %s\n", name, x); - continue; - } else + } + if (!extr) + printf("%s\n", x); + else unlink(x); - continue; - } - if(!extr) - printf("%s\n", x); - else - unlink(x); - } + } + + return 0; } static void @@ -241,7 +258,7 @@ break; *ptr = '0'; } - if(ptr < name + letters) + if (ptr < name + letters) errx(1, "ran out of file names"); } } @@ -293,18 +310,19 @@ name and put in arg string. invent name for unnamed block datas and main programs. */ int -lname(s) +lname(s, len) char *s; +int len; { # define LINESIZE 80 register char *ptr, *p; char line[LINESIZE], *iptr = line; /* first check for comment cards */ - if(buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0); + if (buf[0] == 'c' || buf[0] == 'C' || buf[0] == '*') return(0); ptr = buf; - while (*ptr == ' ' || *ptr == '\t') ptr++; - if(*ptr == '\n') return(0); + trim(ptr); + if (*ptr == '\n') return(0); ptr = skiplab(buf); @@ -324,38 +342,43 @@ if ((ptr = look(line, "subroutine")) != 0 || (ptr = look(line, "function")) != 0 || (ptr = functs(line)) != 0) { - if(scan_name(s, ptr)) return(1); - strcpy( s, x); + if (scan_name(s, ptr, len)) return(1); + strcpy(s, x); } else if((ptr = look(line, "program")) != 0) { - if(scan_name(s, ptr)) return(1); - get_name( mainp, 4); - strcpy( s, mainp); + if(scan_name(s, ptr, len)) return(1); + get_name(mainp, 4); + strcpy(s, mainp); } else if((ptr = look(line, "blockdata")) != 0) { - if(scan_name(s, ptr)) return(1); - get_name( blkp, 6); - strcpy( s, blkp); + if(scan_name(s, ptr, len)) return(1); + get_name(blkp, 6); + strcpy(s, blkp); } else if((ptr = functs(line)) != 0) { - if(scan_name(s, ptr)) return(1); - strcpy( s, x); + if(scan_name(s, ptr, len)) return(1); + strcpy(s, x); } else { - get_name( mainp, 4); - strcpy( s, mainp); + get_name(mainp, 4); + strcpy(s, mainp); } return(1); } int -scan_name(s, ptr) +scan_name(s, ptr, len) char *s, *ptr; +int len; { + int cnt = 0; char *sptr; /* scan off the name */ trim(ptr); sptr = s; while (*ptr != '(' && *ptr != '\n') { - if (*ptr != ' ' && *ptr != '\t') + if (*ptr != ' ' && *ptr != '\t') { *sptr++ = *ptr; + cnt++; + if (cnt == len - 3) break; + } ptr++; } >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message