shithub: trueawk

Download patch

ref: f009bd339788ee01539a74b68a9daf59969163bf
parent: 240201426090f9eca923980e388cab5e66ecc0ef
author: Miguel Pineiro Jr <mpj@pineiro.cc>
date: Mon May 23 13:14:42 EDT 2022

Fix memory leak in string assignment to built-ins

The new string value is always freeable (strdup'd by tostring), so
never mark it as DONTFREE.

$ paste <(./leak.sh master.out) <(./leak.sh fixed.out)
 2564	 2464
 7260	 2476
11948	 2476
16636	 2476
21324	 2476
26012	 2476
30700	 2476
35388	 2476
40076	 2476
44760	 2476
49448	 2476

$ cat leak.sh
#/bin/sh

awk=${1:-nawk}

# Print the initial resident set size
# Assign each record to FS
# Print rsz every 100,000 records
# Exit after a million

yes abcdefghijklmnopqrstuvwxyz | $awk -v mem='ps -p $PPID -o rsz=' '
    BEGIN            { system(mem) }
                     { FS = $0 }
    NR % 100000 == 0 { system(mem) }
    NR == 1000000    { exit }
'

--- a/FIXES
+++ b/FIXES
@@ -25,6 +25,10 @@
 This file lists all bug fixes, changes, etc., made since the AWK book
 was sent to the printers in August, 1987.
 
+May 23, 2022:
+	Memory leak when assigning a string to some of the built-in
+	variables. Thanks to Miguel Pineiro Jr. <mpj@pineiro.cc>.
+
 Mar 3, 2022:
 	Fixed file management memory leak that appears to have been
 	there since the files array was first initialized with stdin,
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@
 THIS SOFTWARE.
 ****************************************************************/
 
-const char	*version = "version 20220303";
+const char	*version = "version 20220523";
 
 #define DEBUG
 #include <stdio.h>
--- a/tran.c
+++ b/tran.c
@@ -70,18 +70,6 @@
 
 extern Cell **fldtab;
 
-static void
-setfree(Cell *vp)
-{
-	if (&vp->sval == FS || &vp->sval == RS ||
-	    &vp->sval == OFS || &vp->sval == ORS ||
-	    &vp->sval == OFMT || &vp->sval == CONVFMT ||
-	    &vp->sval == FILENAME || &vp->sval == SUBSEP)
-		vp->tval |= DONTFREE;
-	else
-		vp->tval &= ~DONTFREE;
-}
-
 void syminit(void)	/* initialize symbol table with builtin vars */
 {
 	literal0 = setsymtab("0", "0", 0.0, NUM|STR|CON|DONTFREE, symtab);
@@ -377,10 +365,9 @@
 	t = s ? tostring(s) : tostring("");	/* in case it's self-assign */
 	if (freeable(vp))
 		xfree(vp->sval);
-	vp->tval &= ~(NUM|CONVC|CONVO);
+	vp->tval &= ~(NUM|DONTFREE|CONVC|CONVO);
 	vp->tval |= STR;
 	vp->fmt = NULL;
-	setfree(vp);
 	DPRINTF("setsval %p: %s = \"%s (%p) \", t=%o r,f=%d,%d\n",
 		(void*)vp, NN(vp->nval), t, (void*)t, vp->tval, donerec, donefld);
 	vp->sval = t;
--