1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix typeset -l/-u crash on special vars (rhbz#1083713)

When using typeset -l or -u on a variable that cannot be changed
when the shell is in restricted mode, ksh crashed.

This fixed is inspired by this Red Hat fix, which is incomplete:
642af4d6/f/ksh-20120801-tpstl.patch

The crash was caused by the nv_shell() function. It walks though a
discipline function tree to get the pointer to the interpreter
associated with it. Evidently, the problem is that some pointer in
that walk is not set correctly for all special variables.

Thing is, ksh only has one shell language interpreter, and only one
global data structure (called 'sh') to keep its main state[*]. Yet,
the code is full of 'shp' pointers to that structure. Most (not
all) functions pass that pointer around to each other, accessing
that struct indirectly, ostensibly to account for the non-existent
possibility that there might be more than one interpreter state.
The "why" of that is an interesting cause for speculation that I
may get to sometime. For now, it is enough to know that, in the
code as it is, it matters not one iota what pointer to the shell
interpreter state is used; they all point to the same thing (unless
it's broken, as in this bug).

So, rather than fixing nv_shell() and/or associated pointer
assignments, this commit simply removes it, and replaces it with
calls to sh_getinterp(), which always returns a pointer to sh (see
init.c, where that function is defined as literally 'return &sh').

[*] Defined in shell.h, with the _SH_PRIVATE part in defs.h

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/name.c:
- Remove nv_shell().

src/cmd/ksh93/sh/init.c:
- In all the discipline functions for special variables, initialise
  shp using sh_getinterp() instead of nv_shell().

src/cmd/ksh93/tests/variables.sh:
- Add regression test for typeset -l/-u on all special variables.
This commit is contained in:
Martijn Dekker 2020-09-23 19:15:45 +02:00
parent 843b546c1a
commit 3654ee73c0
5 changed files with 62 additions and 35 deletions

View file

@ -227,7 +227,7 @@ static void put_ed(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
register const char *cp, *name=nv_name(np);
register int newopt=0;
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
if(*name=='E' && nv_getval(sh_scoped(shp,VISINOD)))
goto done;
if(!(cp=val) && (*name=='E' || !(cp=nv_getval(sh_scoped(shp,EDITNOD)))))
@ -254,7 +254,7 @@ done:
/* Trap for HISTFILE and HISTSIZE variables */
static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
void *histopen = shp->gd->hist_ptr;
char *cp;
if(val && histopen)
@ -278,7 +278,7 @@ static void put_history(register Namval_t* np,const char *val,int flags,Namfun_t
/* Trap for OPTINDEX */
static void put_optindex(Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
shp->st.opterror = shp->st.optchar = 0;
nv_putv(np, val, flags, fp);
if(!val)
@ -303,7 +303,7 @@ static Namfun_t *clone_optindex(Namval_t* np, Namval_t *mp, int flags, Namfun_t
/* Trap for restricted variables FPATH, PATH, SHELL, ENV */
static void put_restricted(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
int path_scoped = 0, fpath_scoped=0;
Pathcomp_t *pp;
char *name = nv_name(np);
@ -345,7 +345,7 @@ static void put_restricted(register Namval_t* np,const char *val,int flags,Namfu
static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Pathcomp_t *pp;
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
nv_putv(np, val, flags, fp);
if(!shp->cdpathlist)
return;
@ -369,7 +369,7 @@ static void put_cdpath(register Namval_t* np,const char *val,int flags,Namfun_t
/* Trap for LC_ALL, LC_CTYPE, LC_MESSAGES, LC_COLLATE and LANG */
static void put_lang(Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
int type;
char *name = nv_name(np);
if(name==(LCALLNOD)->nvname)
@ -494,7 +494,7 @@ static char* get_ifs(register Namval_t* np, Namfun_t *fp)
register struct ifs *ip = (struct ifs*)fp;
register char *cp, *value;
register int c,n;
register Shell_t *shp = nv_shell(np);
register Shell_t *shp = sh_getinterp();
value = nv_getv(np,fp);
if(np!=ip->ifsnp)
{
@ -573,7 +573,7 @@ static void put_seconds(register Namval_t* np,const char *val,int flags,Namfun_t
static char* get_seconds(register Namval_t* np, Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
register int places = nv_size(np);
struct tms tp;
double d, offset = (np->nvalue.dp?*np->nvalue.dp:0);
@ -657,7 +657,7 @@ static Sfdouble_t nget_lineno(Namval_t* np, Namfun_t *fp)
static void put_lineno(Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
register long n;
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
if(!val)
{
fp = nv_stack(np, NIL(Namfun_t*));
@ -681,7 +681,7 @@ static char* get_lineno(register Namval_t* np, Namfun_t *fp)
static char* get_lastarg(Namval_t* np, Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
char *cp;
int pid;
if(sh_isstate(SH_INIT) && (cp=shp->lastarg) && *cp=='*' && (pid=strtol(cp+1,&cp,10)) && *cp=='*')
@ -691,7 +691,7 @@ static char* get_lastarg(Namval_t* np, Namfun_t *fp)
static void put_lastarg(Namval_t* np,const char *val,int flags,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
if(flags&NV_INTEGER)
{
sfprintf(shp->strbuf,"%.*g",12,*((double*)val));
@ -934,7 +934,7 @@ static void math_init(Shell_t *shp)
static Namval_t *create_math(Namval_t *np,const char *name,int flag,Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
if(!name)
return(SH_MATHNOD);
if(name[0]!='a' || name[1]!='r' || name[2]!='g' || name[4] || !isdigit(name[3]) || (name[3]=='0' || (name[3]-'0')>MAX_MATH_ARGS))
@ -945,7 +945,7 @@ static Namval_t *create_math(Namval_t *np,const char *name,int flag,Namfun_t *fp
static char* get_math(register Namval_t* np, Namfun_t *fp)
{
Shell_t *shp = nv_shell(np);
Shell_t *shp = sh_getinterp();
Namval_t *mp,fake;
char *val;
int first=0;
@ -966,7 +966,7 @@ static char* get_math(register Namval_t* np, Namfun_t *fp)
static char *setdisc_any(Namval_t *np, const char *event, Namval_t *action, Namfun_t *fp)
{
Shell_t *shp=nv_shell(np);
Shell_t *shp=sh_getinterp();
Namval_t *mp,fake;
char *name;
int getname=0, off=staktell();

View file

@ -3624,17 +3624,6 @@ int nv_setsize(register Namval_t *np, int size)
return(oldsize);
}
Shell_t *nv_shell(Namval_t *np)
{
Namfun_t *fp;
for(fp=np->nvfun;fp;fp=fp->next)
{
if(!fp->disc)
return((Shell_t*)fp->last);
}
return(0);
}
#undef nv_unset
void nv_unset(register Namval_t *np)