Skip to content

Commit e70925c

Browse files
authored
Fix memory leak on unset of associative array (#64)
Associative arrays weren't being properly freed from memory, which was causing a memory leak. This commit incorporates a patch and reproducer/regress test from: https://www.mail-archive.com/ast-users@lists.research.att.com/msg01016.html src/cmd/ksh93/sh/name.c: - Properly free associative arrays from memory in nv_delete(). src/cmd/ksh93/tests/leaks.sh: - Add regression test.
1 parent bf79131 commit e70925c

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Any uppercase BUG_* names are modernish shell bug IDs.
88
- 'notty' is now written to the ksh auditing file instead of '(null)' if
99
the user's tty could not be determined.
1010

11+
- Unsetting an associative array no longer causes a memory leak to occur.
12+
1113
2020-07-05:
1214

1315
- In UTF-8 locales, fix corruption of the shell's internal string quoting

src/cmd/ksh93/sh/name.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,18 @@ void nv_delete(Namval_t* np, Dt_t *root, int flags)
12981298
if(dtdelete(root,np))
12991299
{
13001300
if(!(flags&NV_NOFREE) && ((flags&NV_FUNCTION) || !nv_subsaved(np)))
1301+
{
1302+
Namarr_t *ap;
1303+
if(nv_isarray(np) && np->nvfun && (ap=nv_arrayptr(np)) && array_assoc(ap))
1304+
{
1305+
/* free associative array from memory */
1306+
while(nv_associative(np,0,NV_ANEXT))
1307+
nv_associative(np,0,NV_ADELETE);
1308+
nv_associative(np,0,NV_AFREE);
1309+
free((void*)np->nvfun);
1310+
}
13011311
free((void*)np);
1312+
}
13021313
}
13031314
#if 0
13041315
else

src/cmd/ksh93/tests/leaks.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,25 @@ done
101101
after=$(getmem)
102102
(( after > before )) && err_exit "memory leak with read -C when using <<< (leaked $((after - before)) $unit)"
103103

104+
# ======
105+
# Unsetting an associative array shouldn't cause a memory leak
106+
# See https://www.mail-archive.com/ast-users@lists.research.att.com/msg01016.html
107+
typeset -A stuff
108+
before=$(getmem)
109+
for (( i=0; i<1000; i++ ))
110+
do
111+
unset stuff[xyz]
112+
typeset -A stuff[xyz]
113+
stuff[xyz][elem0]="data0"
114+
stuff[xyz][elem1]="data1"
115+
stuff[xyz][elem2]="data2"
116+
stuff[xyz][elem3]="data3"
117+
stuff[xyz][elem4]="data4"
118+
done
119+
unset stuff
120+
after=$(getmem)
121+
(( after > before )) && err_exit 'unset of associative array causes memory leak' \
122+
"(leaked $((after - before)) $unit)"
123+
124+
# ======
104125
exit $((Errors<125?Errors:125))

0 commit comments

Comments
 (0)