diff --git a/ChangeLog b/ChangeLog index 17715fc..59d4b07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2018-08-29 Arnold D. Robbins + + * REGRESS: Check for existence of a.out. If not there, run + make. Enable core dumps for T.arnold system status test + to work on MacOS X. + 2018-08-22 Arnold D. Robbins * awktest.tar (testdir/T.expr): Fix test for unary plus. diff --git a/FIXES b/FIXES index d414c6d..909afb7 100644 --- a/FIXES +++ b/FIXES @@ -25,6 +25,11 @@ THIS SOFTWARE. This file lists all bug fixes, changes, etc., made since the AWK book was sent to the printers in August, 1987. +Oct 25, 2018: + Added test in maketab.c to prevent generating a proctab entry + for YYSTYPE_IS_DEFINED. It was harmless but some gcc settings + generated a warning message. Thanks to Nan Xiao for report. + Aug 27, 2018: Disallow '$' in printf formats; arguments evaluated in order and printed in order. diff --git a/REGRESS b/REGRESS index facbd83..7d3ded6 100755 --- a/REGRESS +++ b/REGRESS @@ -1,5 +1,15 @@ #! /bin/sh +case `uname` in +CYGWIN) EXE=a.exe ;; +*) EXE=a.out ;; +esac + +if [ ! -f $EXE ] +then + make || exit 1 +fi + if [ -d testdir ] then true # do nothing @@ -16,5 +26,10 @@ cd testdir pwd PATH=.:$PATH export PATH +if (ulimit -c unlimited > /dev/null 2>&1) +then + # Workaround broken default on MacOS X + ulimit -c unlimited +fi REGRESS diff --git a/bugs-fixed/README b/bugs-fixed/README index 7a9e2c1..1e1bdbe 100644 --- a/bugs-fixed/README +++ b/bugs-fixed/README @@ -24,7 +24,16 @@ and also if CONVFMT changed. 7. unary-plus: Unary plus on a string constant returned the string. Instead, it should convert the value to numeric and give that value. +8. missing-precision: When using the format string "%*s", the precision +argument was used without checking if it was present first. + +9. fmt-overflow: The buffer used for OFMT/CONVFMT conversions was written +to with sprintf(), which meant that some conversions could write past the +end. + X. split-fs-from-array: If the third argument to split() comes from the array passed as the second argument, then split() would previously read from the freed memory and possibly produce incorrect results (depending on the system's malloc()/free() behaviour.) + + diff --git a/bugs-fixed/fmt-overflow.awk b/bugs-fixed/fmt-overflow.awk new file mode 100644 index 0000000..bf5877e --- /dev/null +++ b/bugs-fixed/fmt-overflow.awk @@ -0,0 +1 @@ +BEGIN { OFMT = "%.1000f"; print 1.25; } diff --git a/bugs-fixed/fmt-overflow.ok b/bugs-fixed/fmt-overflow.ok new file mode 100644 index 0000000..5f7449e --- /dev/null +++ b/bugs-fixed/fmt-overflow.ok @@ -0,0 +1 @@ +1.2500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/bugs-fixed/missing-precision.awk b/bugs-fixed/missing-precision.awk new file mode 100644 index 0000000..4e7a74b --- /dev/null +++ b/bugs-fixed/missing-precision.awk @@ -0,0 +1 @@ +BEGIN { printf("%*s"); } diff --git a/bugs-fixed/missing-precision.ok b/bugs-fixed/missing-precision.ok new file mode 100644 index 0000000..608b4fa --- /dev/null +++ b/bugs-fixed/missing-precision.ok @@ -0,0 +1,2 @@ +./a.out: not enough args in printf(%*s) + source line number 1 diff --git a/lex.c b/lex.c index d09f550..ad8e878 100644 --- a/lex.c +++ b/lex.c @@ -198,6 +198,7 @@ int yylex(void) yylval.i = c; switch (c) { case '\n': /* {EOL} */ + lineno++; RET(NL); case '\r': /* assume \n is coming */ case ' ': /* {WS}+ */ @@ -213,6 +214,7 @@ int yylex(void) case '\\': if (peek() == '\n') { input(); + lineno++; } else if (peek() == '\r') { input(); input(); /* \n */ lineno++; @@ -370,10 +372,11 @@ int string(void) case '\n': case '\r': case 0: + *bp = '\0'; SYNTAX( "non-terminated string %.10s...", buf ); - lineno++; if (c == 0) /* hopeless */ FATAL( "giving up" ); + lineno++; break; case '\\': c = input(); @@ -515,6 +518,7 @@ int regexpr(void) if (!adjbuf(&buf, &bufsz, bp-buf+3, 500, &bp, "regexpr")) FATAL("out of space for reg expr %.10s...", buf); if (c == '\n') { + *bp = '\0'; SYNTAX( "newline in regular expression %.10s...", buf ); unput('\n'); break; @@ -553,19 +557,19 @@ int input(void) /* get next lexical input character */ lexprog++; } else /* awk -f ... */ c = pgetc(); - if (c == '\n') - lineno++; - else if (c == EOF) + if (c == EOF) c = 0; if (ep >= ebuf + sizeof ebuf) ep = ebuf; - return *ep++ = c; + *ep = c; + if (c != 0) { + ep++; + } + return (c); } void unput(int c) /* put lexical character back on input */ { - if (c == '\n') - lineno--; if (yysptr >= yysbuf + sizeof(yysbuf)) FATAL("pushed back too much: %.20s...", yysbuf); *yysptr++ = c; diff --git a/makefile b/makefile index ae80e4d..e0a43da 100644 --- a/makefile +++ b/makefile @@ -34,8 +34,8 @@ CC = gcc -g -Wall -pedantic # yacc options. pick one; this varies a lot by system. #YFLAGS = -d -S -#YACC = bison -d -y -YACC = yacc -d +YACC = bison -d -y +#YACC = yacc -d # -S uses sprintf in yacc parser instead of sprint OFILES = b.o main.o parse.o proctab.o tran.o lib.o run.o lex.o diff --git a/maketab.c b/maketab.c index e23974c..bb8e317 100644 --- a/maketab.c +++ b/maketab.c @@ -135,6 +135,8 @@ int main(int argc, char *argv[]) n = sscanf(buf, "%1c %s %s %d", &c, def, name, &tok); if (c != '#' || (n != 4 && strcmp(def,"define") != 0)) /* not a valid #define */ continue; + if (strcmp(name, "YYSTYPE_IS_DECLARED") == 0) + continue; if (tok < FIRSTTOKEN || tok > LASTTOKEN) { /* fprintf(stderr, "maketab funny token %d %s ignored\n", tok, buf); */ continue; diff --git a/run.c b/run.c index 4efa641..a450d7d 100644 --- a/run.c +++ b/run.c @@ -863,6 +863,9 @@ int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like co FATAL("'$' not permitted in awk formats"); } if (*s == '*') { + if (a == NULL) { + FATAL("not enough args in printf(%s)", os); + } x = execute(a); a = a->nnext; sprintf(t-1, "%d", fmtwd=(int) getfval(x)); diff --git a/tran.c b/tran.c index 72ca6ff..6775b01 100644 --- a/tran.c +++ b/tran.c @@ -395,7 +395,7 @@ Awkfloat getfval(Cell *vp) /* get float val of a Cell */ static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cell */ { - char s[100]; /* BUG: unchecked */ + char s[256]; double dtemp; if ((vp->tval & (NUM | STR)) == 0) @@ -434,9 +434,9 @@ static char *get_str_val(Cell *vp, char **fmt) /* get string val of a Cel if (freeable(vp)) \ xfree(vp->sval); \ if (modf(vp->fval, &dtemp) == 0) /* it's integral */ \ - sprintf(s, "%.30g", vp->fval); \ + snprintf(s, sizeof (s), "%.30g", vp->fval); \ else \ - sprintf(s, *fmt, vp->fval); \ + snprintf(s, sizeof (s), *fmt, vp->fval); \ vp->sval = tostring(s); \ vp->tval &= ~DONTFREE; \ vp->tval |= STR; \