bin/72370: awk in -current dumps core

Giorgos Keramidas keramida at freebsd.org
Tue Oct 5 20:10:30 PDT 2004


The following reply was made to PR bin/72370; it has been noted by GNATS.

From: Giorgos Keramidas <keramida at freebsd.org>
To: Joseph Koshy <jkoshy at freebsd.org>
Cc: "David O'Brien" <obrien at freebsd.org>, bug-followup at freebsd.org
Subject: Re: bin/72370: awk in -current dumps core
Date: Wed, 6 Oct 2004 06:06:26 +0300

 On 2004-10-06 02:18, Joseph Koshy <jkoshy at freebsd.org> wrote:
 > awk in 5-current dumps core if asked to deference a positional
 > parameter at a large positive index.  There also seems to be numeric
 > overflow occuring behind the scenes.  The following examples show the
 > difference between GNU awk in 4-STABLE and the awk in 5-current.
 
 Others have reported awk allocating huge amounts of memory if a program
 references a variable with a huge index, which seems to be related to this.
 
 > $ echo | /4/usr/bin/awk '{ x = 2147483648; print $x }'
 > awk: cmd. line:1: (FILENAME=- FNR=1) fatal: attempt to access field -2147483648
 
 Looking at the sources of contrib/one-true-awk I can see several places where
 an overflow/truncation of values can occur.  One example is the code of
 indirect() in run.c which calls getfval() with:
 
 : Awkfloat getfval(Cell *);
 : Cell *indirect(Node **a, int n) /* $( a[0] ) */
 : {
 : 	Cell *x;
 : 	int m;
 :
 : 	m = (int) getfval(x);
 : 	...
 
 There is no guarantee that a plain `int' can hold all the values of an
 Awkfloat, so here's truncation waiting to happen.
 
 The excessive memory allocation is probably caused by the code in lib.c which,
 in the body of the fldbld() function, fails to check for overflow the field
 counter; a plain `int' again:
 
     253 void fldbld(void)       /* create fields from current record */
     254 {
     ...
     259         int i, j, n;
     ...
     278                 for (i = 0; ; ) {
     ...
     283                         i++;
     284                         if (i > nfields)
     285                                 growfldtab(i);
 
 There's no check for an overflow of `i' here, so all sorts of funny things can
 happen if one asks for a large field number.
 
 What you see below:
 
 > $ echo | /4/usr/bin/awk '{ x = 2147483647; print $x }'
 > *blank line*
 > $ echo | /5/usr/bin/awk '{ x = 2147483648; print $x }'
 > /5/usr/bin/awk: trying to access field -2147483648
 > input record number 1, file
 > source line number 1
 
 is a result of the fieldaddr() function in lib.c, which does:
 
     378 Cell *fieldadr(int n)   /* get nth field */
     379 {
     380         if (n < 0)
     381                 FATAL("trying to access field %d", n);
     382         if (n > nfields)        /* fields after NF are empty */
     383                 growfldtab(n);  /* but does not increase NF */
     384         return(fldtab[n]);
     385 }
 
 so negative field numbers are warned about but field numbers greater than the
 existing fields are silently converted to empty strings.
 
 David O'Brien is the one who imported this version of awk in our tree, so he's
 the right person to decide if we can make changes to one-true-awk to fix the
 problems it has or do something else and what that 'something else' should be.


More information about the freebsd-bugs mailing list