diff --git a/NEWS b/NEWS index 721f0d2326d9..f56df356764b 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,12 @@ This documents significant changes in the dev branch of ksh 93u+m. For full details, see the git log at: https://github.com/ksh93/ksh Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. +2024-10-27: + +- Fixed a bug that crashed the shell upon attempting to replace the shell + with another command using 'exec' after unsetting the SHLVL variable. + Bug introduced on 2021-05-18. + 2024-10-23: - Fixed a bug in multidimensional indexed array assignments where unquoted diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c index cb7e883bf239..1d49162694b7 100644 --- a/src/cmd/ksh93/bltins/misc.c +++ b/src/cmd/ksh93/bltins/misc.c @@ -144,7 +144,7 @@ int b_exec(int argc,char *argv[], Shbltin_t *context) return 1; /* if the main shell is about to be replaced, decrease SHLVL to cancel out a subsequent increase */ if(!sh.realsubshell) - (*SHLVL->nvalue.ip)--; + sh.shlvl--; sh_onstate(SH_EXEC); if(sh.subshell && !sh.subshare) { diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h index 866b9c7e301b..d613435148b2 100644 --- a/src/cmd/ksh93/include/shell.h +++ b/src/cmd/ksh93/include/shell.h @@ -276,6 +276,7 @@ struct Shell_s * Programs using libshell should not rely on them as they may change. */ int subshell; /* set for virtual subshell */ int realsubshell; /* ${.sh.subshell}, actual subshell level (including virtual and forked) */ + int32_t shlvl; /* $SHLVL, non-subshell child shell level */ char shcomp; /* set when running shcomp */ unsigned char trapnote; /* set when trap/signal is pending */ struct sh_scoped st; /* scoped information */ diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 6d08843079f8..153490f26fe3 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -18,7 +18,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.1.0-alpha" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2024-10-23" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2024-10-27" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2024 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index 6dce5b41685c..cb38f0500c00 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -221,7 +221,6 @@ static Init_t *nv_init(void); #if SHOPT_STATS static void stat_init(void); #endif -static int shlvl; static int rand_shift; /* @@ -1381,7 +1380,7 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit) nv_putval(ENVNOD,sfstruse(sh.strbuf),NV_RDONLY); } /* increase SHLVL */ - shlvl++; + sh.shlvl++; #if SHOPT_SPAWN { /* @@ -1695,7 +1694,7 @@ void sh_reinit(void) /* Re-import the environment (re-exported in exscript()) */ env_init(); /* Increase SHLVL */ - shlvl++; + sh.shlvl++; /* call user init function, if any */ if(sh.userinit) (*sh.userinit)(&sh, 1); @@ -1825,7 +1824,7 @@ static Init_t *nv_init(void) sh.nvfun.last = (char*)&sh; sh.nvfun.nofree = 1; sh.var_base = sh.var_tree = sh_inittree(shtab_variables); - SHLVL->nvalue.ip = &shlvl; + SHLVL->nvalue.lp = &sh.shlvl; ip->IFS_init.hdr.disc = &IFS_disc; ip->PATH_init.disc = &RESTRICTED_disc; ip->PATH_init.nofree = 1; diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh index f911292909da..a4e857dbc1d2 100755 --- a/src/cmd/ksh93/tests/variables.sh +++ b/src/cmd/ksh93/tests/variables.sh @@ -1677,5 +1677,12 @@ trap 'echo $((foo))' EXIT # throw the echo $((foo)) 'unset parameter' error tw echo $((foo)) EOF +# ====== +# exec after unset SHLVL +# https://github.com/ksh93/ksh/issues/788 +{ "$SHELL" -c 'unset SHLVL; exec true'; } 2>/dev/null +(((e=$?)==0)) || err_exit "crash after unsetting SHLVL" \ + "(expected status 0, got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))" + # ====== exit $((Errors<125?Errors:125))