1
0
Fork 0
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:
Martijn Dekker 2020-08-13 23:29:27 +01:00
parent 64d04e717b
commit 56805b25af
10 changed files with 75 additions and 18 deletions

View file

@ -219,7 +219,7 @@ int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
register int jmpval;
register Shell_t *shp = context->shp;
struct sh_scoped savst, *prevscope = shp->st.self;
char *filename=0, *buffer=0;
char *filename=0, *buffer=0, *tofree;
int fd;
struct dolnod *saveargfor;
volatile struct dolnod *argsave=0;
@ -282,8 +282,9 @@ int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
shp->st.self = &savst;
shp->topscope = (Shscope_t*)shp->st.self;
prevscope->save_tree = shp->var_tree;
tofree = shp->st.filename;
if(np)
shp->st.filename = np->nvalue.rp->fname ? strdup(np->nvalue.rp->fname) : 0;
shp->st.filename = np->nvalue.rp->fname;
nv_putval(SH_PATHNAMENOD, shp->st.filename ,NV_NOFREE);
shp->posix_fun = 0;
if(np || argv[1])
@ -307,7 +308,7 @@ int b_dot_cmd(register int n,char *argv[],Shbltin_t *context)
if(buffer)
free(buffer);
if(!np)
free((void*)shp->st.filename);
free(tofree);
shp->dot_depth--;
if((np || argv[1]) && jmpval!=SH_JMPSCRIPT)
sh_argreset(shp,(struct dolnod*)argsave,saveargfor);