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
= NULLin ksh2020 was added in att/ast@a6b0a828 to fix a Coverity warning (freedoesn’t set pointers toNULLafter 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
tofreevariable, which avoids the kshdb crash sincetofreealways 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
strdupthat was added to fix a crash: https://github.com/ksh93/ksh/blob/05ac1dbb411ee7c4ad5c6d7ae499e72c12be09f6/src/cmd/ksh93/bltins/misc.c#L285-L286When I remove
strdupthe 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
psinstead ofvmstatepoints 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
stkrefis 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: