diff --git a/src/cmd/ksh93/sh/array.c b/src/cmd/ksh93/sh/array.c index fdbc524eb..f409b2631 100644 --- a/src/cmd/ksh93/sh/array.c +++ b/src/cmd/ksh93/sh/array.c @@ -1685,7 +1685,11 @@ void *nv_associative(register Namval_t *np,const char *sp,int mode) ap->header.scope = 0; } else + { + if((ap->header.nelem&ARRAY_MASK)==0 && (ap->cur=nv_search("0",ap->header.table,0))) + nv_associative(np,(char*)0,NV_ADELETE); dtclose(ap->header.table); + } return((void*)ap); case NV_ANEXT: if(!ap->pos) diff --git a/src/cmd/ksh93/sh/name.c b/src/cmd/ksh93/sh/name.c index 604b2cc4d..e2f5de88f 100644 --- a/src/cmd/ksh93/sh/name.c +++ b/src/cmd/ksh93/sh/name.c @@ -2404,6 +2404,8 @@ static void table_unset(Shell_t *shp, register Dt_t *root, int flags, Dt_t *oroo } } npnext = (Namval_t*)dtnext(root,np); + if(nv_arrayptr(np)) + nv_putsub(np,NIL(char*),ARRAY_SCAN); _nv_unset(np,flags); nv_delete(np,root,0); } @@ -3256,7 +3258,7 @@ int nv_rename(register Namval_t *np, int flags) shp->last_root = last_root; if(flags&NV_MOVE) { - if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp))) + if(arraynp && !nv_isattr(np,NV_MINIMAL) && (mp=(Namval_t*)np->nvenv) && (ap=nv_arrayptr(mp)) && !ap->fun) ap->nelem++; } if((nv_arrayptr(nr) && !arraynr) || nv_isvtree(nr)) diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh index 38e0652e1..0ea4795fd 100755 --- a/src/cmd/ksh93/tests/leaks.sh +++ b/src/cmd/ksh93/tests/leaks.sh @@ -193,5 +193,40 @@ done after=$(getmem) err_exit_if_leak 'script sourced in virtual subshell' +# ====== +# Multiple leaks when using arrays in functions (Red Hat #921455) +# Fix based on: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik.patch + +# TODO: both of these tests still leak (although much less after the patch) when run in a non-C locale. +saveLANG=$LANG; LANG=C # comment out to test remaining leak (1/2) + +function _hash +{ + typeset w=([abc]=1 [def]=31534 [xyz]=42) + print -u2 $w 2>&- + # accessing the var will leak +} +before=$(getmem) +for ((i=0; i < N; i++)) +do _hash +done +after=$(getmem) +err_exit_if_leak 'associative array in function' + +function _array +{ + typeset w=(1 31534 42) + print -u2 $w 2>&- + # unset w will prevent leak +} +before=$(getmem) +for ((i=0; i < N; i++)) +do _array +done +after=$(getmem) +err_exit_if_leak 'indexed array in function' + +LANG=$saveLANG # comment out to test remaining leak (2/2) + # ====== exit $((Errors<125?Errors:125))