ksh: Memory leak and eventual crash when defining and running function in virtual subshell
This bug was discovered and identified as separate while fixing #113.
When defining and running function in a (virtual/non-forked) subshell many times, a crash occurs.
Reproducer (minimal except for the counter):
for ((n=0; n < 50000; n++))
do print -n $'\r'$n # optional counter
(function foo { :; }; foo)
done
When compiled with vmalloc, the reproducer consistently crashes at iteration #32766. This is 2^15-2, suggesting an overflow of a short
somewhere (max value: 2^15-1, 32767).
When compiled without vmalloc and using the native malloc on macOS, it crashes slightly later and at unpredictable numbers of iterations, but all quite close to a short
overflow: 32907, 33191, 32986, 33038, 32832, 32783, etc.
Backtraces of the native macOS malloc crash are here.
The consistent crash with vmalloc always has the same backtrace (edit: updated with backtrace with source line numbers after recompiling with -O0 -g
):
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 ksh 0x000000010f5fd8d0 _sfpmove + 80 (sfpool.c:235)
1 ksh 0x000000010f5f16c5 sfclose + 837 (sfclose.c:96)
2 ksh 0x000000010f5b6469 stkclose + 121 (stk.c:317)
3 ksh 0x000000010f562bb2 sh_exec + 10674 (xec.c:1516)
4 ksh 0x000000010f564a99 sh_exec + 18585 (xec.c:2012)
5 ksh 0x000000010f55c7ed sh_subshell + 2605 (subshell.c:605)
6 ksh 0x000000010f564402 sh_exec + 16898 (xec.c:1886)
7 ksh 0x000000010f564a99 sh_exec + 18585 (xec.c:2012)
8 ksh 0x000000010f56571c sh_exec + 21788 (xec.c:2201)
9 ksh 0x000000010f564a99 sh_exec + 18585 (xec.c:2012)
10 ksh 0x000000010f4e7dbb exfile + 3243 (main.c:582)
11 ksh 0x000000010f4e8ce7 sh_main + 3367 (main.c:353)
12 ksh 0x000000010f4ce796 main + 38 (pmain.c:45)
13 libdyld.dylib 0x00007fff670df3d5 start + 1
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 22
Specifying a
(void*)
cast is unnecessary when usingfree
(free(tofree)
is equivalent tofree((void*)tofree)
). In fact, the abovefree(buffer)
is freeing achar *
variable, yet it doesn’t have a cast: https://github.com/ksh93/ksh/blob/05ac1dbb411ee7c4ad5c6d7ae499e72c12be09f6/src/cmd/ksh93/bltins/misc.c#L222 https://github.com/ksh93/ksh/blob/05ac1dbb411ee7c4ad5c6d7ae499e72c12be09f6/src/cmd/ksh93/bltins/misc.c#L307-L308This is the ksh2020 code that frees
shp->st.filename
(link)The extra
= NULL
in ksh2020 was added in att/ast@a6b0a828 to fix a Coverity warning (free
doesn’t set pointers toNULL
after freeing memory).The following patch fixes the POSIX function memory leak without reintroducing the kshdb crash. This makes ksh free the memory pointed to by a
tofree
variable, which avoids the kshdb crash sincetofree
always points to memory that can be freed:The shcomp leak increases as you increase the number of iterations N. But at exactly N=6400, the shcomp leak magically goes away, and at larger numbers (such as N=10000, or even N=100000) it doesn’t return. Perhaps this is one of those vmalloc bizarritudes.
The memory leak in POSIX functions is a regression caused by bd88cc7f, specifically the
strdup
that was added to fix a crash: https://github.com/ksh93/ksh/blob/05ac1dbb411ee7c4ad5c6d7ae499e72c12be09f6/src/cmd/ksh93/bltins/misc.c#L285-L286When I remove
strdup
the memory leak test has the following results:The following patch, based on the check from name.c (above), fixes this bug for me while not introducing att#803. @JohnoKing, could you test and confirm this? Does this look good to you?
The memory leak appears to be fixed in ksh93v- 2014-12-24 beta. Running the same example in ksh2020 with
ps
instead ofvmstate
points to the memory leak returning after ksh93v- as a ksh2020 regression:Hmm, I’m not convinced of that – that
<=
looks like it might as well be==
. Seems more like a ‘just to be extra sure’ kind of thing.But that suggests
stkref
is supposed to decrement, and isn’t decrementing, as it overflows.Which makes me wonder if there is a memory leak.
Test script:
And sure enough: