mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Fix leak and crash upon defining functions in subshells
A memory leak occurred upon leaving a virtual subshell if a
function was defined within it. If this was done more than 32766
(= 2^15-2 = the 'short' max value - 1) times, the shell crashed.
Discussion and reproducer: https://github.com/ksh93/ksh/issues/114
src/cmd/ksh93/sh/subshell.c: table_unset():
- A subshell-defined function was never freed because a broken
check for autoloaded functions (which must not be freed[*]). It
looked for an initial '/' in the canonical path of the script
file that defined the function, but that path is also stored for
regular functions. Now use a check that executes nv_search() in
fpathdict, the same method used in _nv_unset() in name.c for a
regular function unset.
src/cmd/ksh93/bltins/misc.c: b_dot_cmd():
- Fix an additional memory leak introduced in bd88cc7f
, that caused
POSIX functions (which are run with b_dot_cmd() like dot scripts)
to leak extra. This fix avoids both the crash fixed there and the
memory leak by introducing a 'tofree' variable remembering the
filename to free. Thanks to Johnothan King for the patch.
src/lib/libast/include/stk.h,
src/lib/libast/misc/stk.c,
src/lib/libast/man/stk.3,
src/lib/libast/man/stak.3:
- Make the stack more resilient by extending the stack reference
counter 'stkref' from (signed) short to unsigned int. On modern
systems with 32-bit ints, this extends the maximum number of
elements on a stack from 2^15-1==32767 to 2^32-1==4294967295.
The ref counter can never be negative, so there is no reason for
signedness. sizeof(int) is defined as the size of a single CPU
word, so this should not affect performance at all.
On a 16-bit system (not that ksh still compiles there), this
doubles the max number of entries to 2^16-1=65535.
src/cmd/ksh93/tests/leaks.sh:
- Add leak regression tests for ksh functions, POSIX functions, dot
scripts run with '.', and dot scripts run with 'source'.
src/cmd/ksh93/tests/path.sh:
- Add an output builtin with a redirect to an autoloaded function
so that a crash[*] is triggered if the check for an autoloaded
function is ever removed from table_unset(), as was done in ksh
93v- (which crashed).
[*] Freeing autoloaded functions after leaving a virtual subshell
causes a crashing bug: https://github.com/att/ast/issues/803
Co-authored-by: Johnothan King <johnothanking@protonmail.com>
Fixes: https://github.com/ksh93/ksh/issues/114
This commit is contained in:
parent
64d04e717b
commit
56805b25af
10 changed files with 75 additions and 18 deletions
|
@ -397,7 +397,11 @@ Dt_t *sh_subfuntree(int create)
|
|||
return(sp->shp->fun_tree);
|
||||
}
|
||||
|
||||
static void table_unset(register Dt_t *root,int fun)
|
||||
/*
|
||||
* Remove and free a subshell table at *root after leaving a virtual subshell.
|
||||
* Pass 'fun' as nonzero when removing a subshell's shell functions.
|
||||
*/
|
||||
static void table_unset(Shell_t *shp,register Dt_t *root,int fun)
|
||||
{
|
||||
register Namval_t *np,*nq;
|
||||
int flag;
|
||||
|
@ -405,7 +409,9 @@ static void table_unset(register Dt_t *root,int fun)
|
|||
{
|
||||
nq = (Namval_t*)dtnext(root,np);
|
||||
flag=0;
|
||||
if(fun && np->nvalue.rp && np->nvalue.rp->fname && *np->nvalue.rp->fname=='/')
|
||||
/* Check for autoloaded function; it must not be freed. */
|
||||
if(fun && np->nvalue.rp && np->nvalue.rp->fname && shp->fpathdict
|
||||
&& nv_search(np->nvalue.rp->fname,shp->fpathdict,0))
|
||||
{
|
||||
np->nvalue.rp->fdict = 0;
|
||||
flag = NV_NOFREE;
|
||||
|
@ -693,7 +699,7 @@ Sfio_t *sh_subshell(Shell_t *shp,Shnode_t *t, volatile int flags, int comsub)
|
|||
if(sp->sfun)
|
||||
{
|
||||
shp->fun_tree = dtview(sp->sfun,0);
|
||||
table_unset(sp->sfun,1);
|
||||
table_unset(shp,sp->sfun,1);
|
||||
dtclose(sp->sfun);
|
||||
}
|
||||
n = shp->st.trapmax-savst.trapmax;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue