two fixes for awk
Carl Sutton
sutton at daemon.UUCP
Thu Apr 11 09:59:47 AEST 1985
Synopsis: awk does odd things with substr or field setting
Description:
Recently, I fixed a bug that was causing `substr' to misbehave or
fields to remain unset in the record. There is some history.
Apparently some time ago there was a fix to the field problem
posted to the net. It was a hack fix involving
redefining an `EMPTY' string to be a null pointer
(as opposed to a pointer to a zero length string).
This historic fix causes a problem with `substr' which
can core dump or otherwise misbehave with a null pointer.
Repeat by:
Repeating the bug depends on whether the earlier fix was
installed. Try each of the following.
1. Create a file with a bunch of empty lines (newlines only)
and run the follwing command:
awk '{s = substr($1, 1, 1)}' file
2. Try the following:
echo 'now is the time' >file
awk '{ $1 = "then"; print $0 }' file
Fix:
Backout the historic fix if it was installed. Following are
diffs for backing out the old fix in awk.def and lib.c
and installing the new in tran.c. You will probably want
to install these by hand.
The proper fix involves ferreting out the actual inconsistency
in the souce code in the determination of an `EMPTY' string.
RCS file: RCS/lib.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -c -r1.2 -r1.3
*** /tmp/,RCSt1008065 Wed Apr 10 15:44:38 1985
--- /tmp/,RCSt2008065 Wed Apr 10 15:44:48 1985
***************
*** 1,8
/*
* $Log: lib.c,v $
! * Revision 1.2 84/10/24 18:58:20 root
! * Part of fix to change EMPTY[] to #define EMPTY NULL
! * -rdoty at tek
*
* Revision 1.1 84/09/10 16:37:59 root
* Initial revision
--- 1,9 -----
/*
* $Log: lib.c,v $
! * Revision 1.3 85/02/22 16:16:22 sutton
! * This is revision 1.1 retrieved
! * from the past. The purpose is to
! * back out the fix made in 1.2.
*
* Revision 1.1 84/09/10 16:37:59 root
* Initial revision
***************
*** 22,27
#define RECSIZE (5 * 512)
char record[RECSIZE];
char fields[RECSIZE];
#define MAXFLD 100
int donefld; /* 1 = implies rec broken into fields */
--- 23,29 -----
#define RECSIZE (5 * 512)
char record[RECSIZE];
char fields[RECSIZE];
+ char EMPTY[] = "";
#define MAXFLD 100
int donefld; /* 1 = implies rec broken into fields */
RCS file: RCS/awk.def,v
retrieving revision 1.2
retrieving revision 1.3
diff -c -r1.2 -r1.3
*** /tmp/,RCSt1008107 Wed Apr 10 15:46:47 1985
--- /tmp/,RCSt2008107 Wed Apr 10 15:46:52 1985
***************
*** 1,8
/*
* $Log: awk.def,v $
! * Revision 1.2 84/10/24 18:59:21 root
! * Part of fix to change EMPTY[] to #define EMPTY NULL
! * -rdoty at tek
*
* Revision 1.1 84/09/10 16:42:58 root
* Initial revision
--- 1,9 -----
/*
* $Log: awk.def,v $
! * Revision 1.3 85/02/22 16:17:48 sutton
! * This is revision 1.1 retrieved
! * from the past. The purpose is to
! * back out the fix made in 1.2.
*
* Revision 1.1 84/09/10 16:42:58 root
* Initial revision
***************
*** 11,17
/* awk.def 4.2 83/02/09 */
#define hack int
- #define EMPTY NULL
#define AWKFLOAT float
#define xfree(a) { if(a!=NULL) { yfree(a); a=NULL;} }
#define strfree(a) { if(a!=NULL && a!=EMPTY) { yfree(a);} a=EMPTY; }
--- 12,17 -----
/* awk.def 4.2 83/02/09 */
#define hack int
#define AWKFLOAT float
#define xfree(a) { if(a!=NULL) { yfree(a); a=NULL;} }
#define strfree(a) { if(a!=NULL && a!=EMPTY) { yfree(a);} a=EMPTY; }
***************
*** 33,38
extern char **FILENAME;
extern char record[];
extern int dbg;
extern int lineno;
extern int errorflag;
--- 33,39 -----
extern char **FILENAME;
extern char record[];
+ extern char EMPTY[];
extern int dbg;
extern int lineno;
extern int errorflag;
RCS file: RCS/tran.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** /tmp/,RCSt1007086 Wed Apr 10 14:49:29 1985
--- /tmp/,RCSt2007086 Wed Apr 10 14:49:37 1985
***************
*** 1,5
/*
* $Log: tran.c,v $
* Revision 1.1 84/09/10 16:39:49 root
* Initial revision
*
--- 1,15 -----
/*
* $Log: tran.c,v $
+ * Revision 1.2 85/02/22 16:19:52 sutton
+ * Fixed an inconsistency in setsval and
+ * setfval. The nval member of struct cell
+ * is initialized to EMPTY. setsval and
+ * setfval were testing (nval == 0) to decide
+ * whether the cell whose value was set was
+ * a field. If a field is set, then the record
+ * must be rebuilt when next refered to in
+ * the awk script.
+ *
* Revision 1.1 84/09/10 16:39:49 root
* Initial revision
*
***************
*** 142,148
error(FATAL, "can't set $0");
vp->tval &= ~STR; /* mark string invalid */
vp->tval |= NUM; /* mark number ok */
! if ((vp->tval & FLD) && vp->nval == 0)
donerec = 0;
return(vp->fval = f);
}
--- 152,158 -----
error(FATAL, "can't set $0");
vp->tval &= ~STR; /* mark string invalid */
vp->tval |= NUM; /* mark number ok */
! if ((vp->tval & FLD) && vp->nval == EMPTY)
donerec = 0;
return(vp->fval = f);
}
***************
*** 157,163
error(FATAL, "can't set $0");
vp->tval &= ~NUM;
vp->tval |= STR;
! if ((vp->tval & FLD) && vp->nval == 0)
donerec = 0;
if (!(vp->tval&FLD))
strfree(vp->sval);
--- 167,173 -----
error(FATAL, "can't set $0");
vp->tval &= ~NUM;
vp->tval |= STR;
! if ((vp->tval & FLD) && vp->nval == EMPTY)
donerec = 0;
if (!(vp->tval&FLD))
strfree(vp->sval);
**************************************************************
Synopsis: awk dies on a floating exception
Description:
awk attempts to determine whether each field in
an input record may properly be interpreted as
a floating point number. If the magnitude of
potential number is too large or too small, then
the number is left as a string.
`isnumber' is incorrectly calculating the
magnitude of the number and thus allowing
awk to attempt to convert a number that is
actually too large.
To Reproduce:
echo 8300E36 >xx
awk '{ print $1 }' xx
Floating Exception (core dumped)
Fix:
Make `isnumber' correctly determine the magnitude of
a potential number.
RCS file: RCS/lib.c,v
retrieving revision 1.1
retrieving revision 1.4
diff -c -r1.1 -r1.4
*** /tmp/,RCSt1007074 Wed Apr 10 14:48:32 1985
--- /tmp/,RCSt2007074 Wed Apr 10 14:48:40 1985
***************
*** 1,5
/*
* $Log: lib.c,v $
* Revision 1.1 84/09/10 16:37:59 root
* Initial revision
*
--- 1,19 -----
/*
* $Log: lib.c,v $
+ * Revision 1.4 85/03/20 13:08:20 sutton
+ * Routine isnumber() attempts to determine
+ * the magnitude of a potential number before
+ * actual conversion of the string to a value.
+ * The magnitude was incorrectly calculated.
+ * This was causing atof() to be called for an
+ * argument that could potentially not fit in
+ * the type `awkfloat'.
+ *
+ * Revision 1.3 85/02/22 16:16:22 sutton
+ * This is revision 1.1 retrieved
+ * from the past. The purpose is to
+ * back out the fix made in 1.2.
+ *
* Revision 1.1 84/09/10 16:37:59 root
* Initial revision
*
***************
*** 279,285
} while (isdigit(*s));
if (s - es > 2)
return(0);
! else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON)
return(0);
}
while (*s == ' ' || *s == '\t' || *s == '\n')
--- 293,299 -----
} while (isdigit(*s));
if (s - es > 2)
return(0);
! else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' + d1 >= MAXEXPON)
return(0);
}
while (*s == ' ' || *s == '\t' || *s == '\n')
***************************************************
Carl Sutton
tektronix!sutton
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list