guy%gorodish@Sun.COM (Guy Harris) (09/26/87)
These are some fixes to the S5R2 "awk" that fix some null-pointer dereferencing problems, clean up the code slightly, and keep it from terminating without cleaning up after programs kicked off by "| <command>" constructs (the latter fix comes from 4.3BSD). These fixes probably apply in a fairly straightforward fashion to the S5R3 and S5R3.1 versions; I think they are already in the "new awk" in S5R3.1. If you have an "awk" that antedates the S5R2 version, you should pick up the S5R2 version because it is significantly faster; if you can't, just pick up the 4.3BSD version instead, it has most of these fixes in it. diff -c /archbeluga/s5r2/usr/src/cmd/awk/awk.def ./awk.def *** /archbeluga/s5r2/usr/src/cmd/awk/awk.def Mon Jul 4 11:01:04 1983 --- ./awk.def Wed Feb 4 14:11:57 1987 *************** *** 16,22 **** extern awkfloat *NF; extern char **FILENAME; ! extern char *record; extern int dbg; extern int lineno; extern int errorflag; --- 16,22 ---- extern awkfloat *NF; extern char **FILENAME; ! extern char record[]; extern int dbg; extern int lineno; extern int errorflag; *************** *** 71,77 **** } NODE; extern NODE *winner; - extern NODE *nullstat; /* ctypes */ #define OCELL 1 --- 71,76 ---- diff -c /archbeluga/s5r2/usr/src/cmd/awk/awk.g.y ./awk.g.y *** /archbeluga/s5r2/usr/src/cmd/awk/awk.g.y Mon Jul 4 11:01:04 1983 --- ./awk.g.y Wed Feb 4 14:11:29 1987 *************** *** 236,242 **** { $$ = stat3($1, $2, 0, 0); } | expr { $$ = exptostat($1); } | { $$ = (int)0; } ! | error { yyclearin; yyerror("illegal statement"); } ; statement: --- 236,242 ---- { $$ = stat3($1, $2, 0, 0); } | expr { $$ = exptostat($1); } | { $$ = (int)0; } ! | error { yyclearin; yyerror("illegal statement"); $$ = (int)0; } ; statement: diff -c /archbeluga/s5r2/usr/src/cmd/awk/lib.c ./lib.c *** /archbeluga/s5r2/usr/src/cmd/awk/lib.c Mon Jul 4 11:01:06 1983 --- ./lib.c Wed Feb 4 14:11:06 1987 *************** *** 6,14 **** FILE *infile = NULL; char *file; #define RECSIZE (5 * 512) ! char recdata[RECSIZE]; ! char *record = recdata; char fields[RECSIZE]; #define MAXFLD 100 int donefld; /* 1 = implies rec broken into fields */ --- 6,14 ---- FILE *infile = NULL; char *file; #define RECSIZE (5 * 512) ! char record[RECSIZE]; char fields[RECSIZE]; + static char EMPTY[] = ""; #define MAXFLD 100 int donefld; /* 1 = implies rec broken into fields */ *************** *** 15,23 **** int donerec; /* 1 = record is valid (no flds have changed) */ int mustfld; /* 1 = NF seen, so always break*/ ! #define FINIT { OCELL, CFLD, 0, NULL, 0.0, FLD|STR } CELL fldtab[MAXFLD] = { /* room for fields */ ! { OCELL, CFLD, "$record", recdata, 0.0, STR|FLD}, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, --- 15,23 ---- int donerec; /* 1 = record is valid (no flds have changed) */ int mustfld; /* 1 = NF seen, so always break*/ ! #define FINIT { OCELL, CFLD, 0, EMPTY, 0.0, FLD|STR } CELL fldtab[MAXFLD] = { /* room for fields */ ! { OCELL, CFLD, "$record", record, 0.0, STR|FLD}, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, *************** *** 112,118 **** { register char *r, *fr, sep; CELL *p, *q; - static char *nullstat = ""; int i, j; r = record; --- 112,117 ---- *************** *** 165,171 **** if (!(p->tval&FLD)) xfree(p->sval); p->tval = STR | FLD; ! p->sval = nullstat; } maxfld = i; donefld = 1; --- 164,170 ---- if (!(p->tval&FLD)) xfree(p->sval); p->tval = STR | FLD; ! p->sval = EMPTY; } maxfld = i; donefld = 1; *************** *** 221,227 **** fprintf(stderr, "awk: "); fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); fprintf(stderr, "\n"); ! if (*NR > 0) fprintf(stderr, " record number %g\n", *NR); if (f) exit(2); --- 220,226 ---- fprintf(stderr, "awk: "); fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); fprintf(stderr, "\n"); ! if (NR && *NR > 0) fprintf(stderr, " record number %g\n", *NR); if (f) exit(2); diff -c /archbeluga/s5r2/usr/src/cmd/awk/run.c ./run.c *** /archbeluga/s5r2/usr/src/cmd/awk/run.c Mon Jul 4 11:01:08 1983 --- ./run.c Wed Feb 4 14:09:52 1987 *************** *** 6,17 **** #include "awk.h" #include "stdio.h" ! #define RECSIZE 512 #define FILENUM 10 struct { FILE *fp; char *fname; } files[FILENUM]; FILE *popen(); --- 6,18 ---- #include "awk.h" #include "stdio.h" ! #define RECSIZE BUFSIZ #define FILENUM 10 struct { FILE *fp; + int type; char *fname; } files[FILENUM]; FILE *popen(); *************** *** 40,46 **** --- 41,54 ---- run(a) NODE *a; { + register int i; + execute(a); + + /* Wait for children to complete if output to a pipe. */ + for (i=0; i<FILENUM; i++) + if (files[i].fp && files[i].type == '|') + pclose(files[i].fp); } CELL *execute(u) NODE *u; *************** *** 86,96 **** } while (getrec()) { x = execute(a[1]); ! if (isexit(x)) break; tempfree(x); } - tempfree(x); if (a[2] != NULL) { x = execute(a[2]); if (isbreak(x) || isnext(x) || iscont(x)) --- 94,105 ---- } while (getrec()) { x = execute(a[1]); ! if (isexit(x)) { ! tempfree(x); break; + } tempfree(x); } if (a[2] != NULL) { x = execute(a[2]); if (isbreak(x) || isnext(x) || iscont(x)) *************** *** 186,191 **** --- 195,201 ---- default: error(FATAL, "unknown boolean operator %d", n); } + /*NOTREACHED*/ } CELL *relop(a,n) NODE **a; *************** *** 220,225 **** --- 230,236 ---- default: error(FATAL, "unknown relational operator %d", n); } + /*NOTREACHED*/ } *************** *** 329,334 **** --- 340,347 ---- os = s; p = buf = (char *)malloc(RECSIZE); + if (p == NULL) + error(FATAL, "out of space in format"); while (*s) { if (*s != '%') { *p++ = *s++; *************** *** 378,389 **** error(FATAL, "not enough arguments in printf(%s)", os); x = execute(a); a = a->nnext; ! if (flag != 4) /* watch out for converting to numbers! */ xf = getfval(x); ! if (flag == 1) sprintf(p, fmt, xf); ! else if (flag == 2) sprintf(p, fmt, (long)xf); ! else if (flag == 3) sprintf(p, fmt, (int)xf); ! else if (flag == 4) sprintf(p, fmt, x->sval==NULL ? "" : getsval(x)); tempfree(x); p += strlen(p); s++; --- 391,404 ---- error(FATAL, "not enough arguments in printf(%s)", os); x = execute(a); a = a->nnext; ! if (flag == 4) /* watch out for converting to numbers! */ ! sprintf(p, fmt, getsval(x)); ! else { xf = getfval(x); ! if (flag == 1) sprintf(p, fmt, xf); ! else if (flag == 2) sprintf(p, fmt, (long)xf); ! else if (flag == 3) sprintf(p, fmt, (int)xf); ! } tempfree(x); p += strlen(p); s++; *************** *** 536,542 **** getsval(y); n1 = strlen(x->sval); n2 = strlen(y->sval); ! s = (char *) malloc(n1 + n2 + 1); strcpy(s, x->sval); strcpy(s+n1, y->sval); tempfree(y); --- 551,558 ---- getsval(y); n1 = strlen(x->sval); n2 = strlen(y->sval); ! if ((s = (char *) malloc(n1 + n2 + 1)) == NULL) ! error(FATAL, "out of space in cat"); strcpy(s, x->sval); strcpy(s+n1, y->sval); tempfree(y); *************** *** 711,716 **** --- 727,733 ---- return(x); tempfree(x); } + /*NOTREACHED*/ } CELL *forstat(a,n) NODE **a; *************** *** 763,768 **** --- 780,786 ---- tempfree(x); } } + return (true); } CELL *jump(a, n) NODE **a; *************** *** 785,790 **** --- 803,809 ---- default: error(FATAL, "illegal jump type %d", n); } + /*NOTREACHED*/ } CELL *fncn(a,n) NODE **a; *************** *** 861,867 **** x = execute(b); getsval(x); for (i=0; i<FILENUM; i++) ! if (strcmp(x->sval, files[i].fname) == 0) goto doit; for (i=0; i<FILENUM; i++) if (files[i].fp == 0) --- 880,886 ---- x = execute(b); getsval(x); for (i=0; i<FILENUM; i++) ! if (files[i].fp != 0 && strcmp(x->sval, files[i].fname) == 0) goto doit; for (i=0; i<FILENUM; i++) if (files[i].fp == 0) *************** *** 877,882 **** --- 896,902 ---- if (files[i].fp == NULL) error(FATAL, "can't open file %s", x->sval); files[i].fname = tostring(x->sval); + files[i].type = a; doit: fprintf(files[i].fp, "%s", s); #ifndef gcos Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com