mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
This should fix various crashes that remain, at least:
* when running a PS2 discipline at parse time
* when pressing Ctrl+C on a PS2 prompt
* when a special builtin within a discipline throws an error within
a virtual subshell
src/cmd/ksh93/sh/nvdisc.c:
- In both assign() which handles .set disciplines and lookup()
which handles .get disciplines, to stop errors in discipline
functions from wreaking havoc:
- Save, reinitialise and restore the lexer state in case the
discipline is run at parse time. This happens with PS2; I'm not
currently aware of other contexts but that doesn't mean there
aren't any or that there won't be any. Plus, I determined by
experimenting that doing this here seems to be the only way to
make it work reliably. Thankfully the overhead is low.
- Check the topfd redirection state and run sh_iorestore() if
needed. Without this, if a special builtin with a redirection
throws an error in a discipline function, its redirection(s)
remain permanent. For example, 'trap --bad-option 2>/dev/null'
in a PS2.get() discipline would kill standard error, including
all your prompts.
src/cmd/ksh93/sh/io.c: io_prompt():
- Before getting the value of the PS2 prompt, save the stack state
and restore it after. This stops a PS2.get discipline function
from corrupting a command substitution that the user is typing.
Doing this in assign()/lookup() is ineffective, so do it here.
Fixes: https://github.com/ksh93/ksh/issues/347
This commit is contained in:
parent
1f5ad85cd4
commit
a2bc49bed1
4 changed files with 61 additions and 11 deletions
|
|
@ -2186,8 +2186,15 @@ static int io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
|
|||
goto done;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
/* PS2 prompt. Save stack state to avoid corrupting command substitutions
|
||||
* in case we're executing a PS2.get discipline function at parse time. */
|
||||
int savestacktop = staktell();
|
||||
char *savestackptr = stakfreeze(0);
|
||||
cp = nv_getval(sh_scoped(shp,PS2NOD));
|
||||
stakset(savestackptr, savestacktop);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
cp = nv_getval(sh_scoped(shp,PS3NOD));
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "variables.h"
|
||||
#include "builtins.h"
|
||||
#include "path.h"
|
||||
#include "io.h"
|
||||
#include "shlex.h"
|
||||
|
||||
static void assign(Namval_t*,const char*,int,Namfun_t*);
|
||||
|
||||
|
|
@ -283,21 +285,30 @@ static void assign(Namval_t *np,const char* val,int flags,Namfun_t *handle)
|
|||
nq = vp->disc[type=UNASSIGN];
|
||||
if(nq && !isblocked(bp,type))
|
||||
{
|
||||
int bflag=0, savexit=sh.savexit, jmpval=0;
|
||||
struct checkpt buff;
|
||||
struct checkpt checkpoint;
|
||||
int jmpval;
|
||||
int savexit = sh.savexit;
|
||||
Lex_t *lexp = (Lex_t*)sh.lex_context, savelex;
|
||||
int bflag;
|
||||
/* disciplines like PS2 may run at parse time; save, reinit and restore the lexer state */
|
||||
savelex = *lexp;
|
||||
sh_lexopen(lexp, &sh, 0); /* needs full init (0), not what it calls reinit (1) */
|
||||
block(bp,type);
|
||||
if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
|
||||
if(bflag = (type==APPEND && !isblocked(bp,LOOKUPS)))
|
||||
block(bp,LOOKUPS);
|
||||
sh_pushcontext(&sh,&buff,1);
|
||||
jmpval = sigsetjmp(buff.buff,0);
|
||||
sh_pushcontext(&sh, &checkpoint, 1);
|
||||
jmpval = sigsetjmp(checkpoint.buff, 0);
|
||||
if(!jmpval)
|
||||
sh_fun(nq,np,(char**)0);
|
||||
sh_popcontext(&sh,&buff);
|
||||
sh_popcontext(&sh, &checkpoint);
|
||||
if(sh.topfd != checkpoint.topfd)
|
||||
sh_iorestore(&sh, checkpoint.topfd, jmpval);
|
||||
unblock(bp,type);
|
||||
if(bflag)
|
||||
unblock(bp,LOOKUPS);
|
||||
if(!vp->disc[type])
|
||||
chktfree(np,vp);
|
||||
*lexp = savelex;
|
||||
sh.savexit = savexit; /* avoid influencing $? */
|
||||
}
|
||||
if(nv_isarray(np))
|
||||
|
|
@ -381,8 +392,13 @@ static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
|
|||
union Value *up = np->nvalue.up;
|
||||
if(nq && !isblocked(bp,type))
|
||||
{
|
||||
int savexit = sh.savexit, jmpval = 0;
|
||||
struct checkpt buff;
|
||||
struct checkpt checkpoint;
|
||||
int jmpval;
|
||||
int savexit = sh.savexit;
|
||||
Lex_t *lexp = (Lex_t*)sh.lex_context, savelex;
|
||||
/* disciplines like PS2 may run at parse time; save, reinit and restore the lexer state */
|
||||
savelex = *lexp;
|
||||
sh_lexopen(lexp, &sh, 0); /* needs full init (0), not what it calls reinit (1) */
|
||||
node = *SH_VALNOD;
|
||||
if(!nv_isnull(SH_VALNOD))
|
||||
{
|
||||
|
|
@ -395,11 +411,13 @@ static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
|
|||
nv_setsize(SH_VALNOD,10);
|
||||
}
|
||||
block(bp,type);
|
||||
sh_pushcontext(&sh,&buff,1);
|
||||
jmpval = sigsetjmp(buff.buff,0);
|
||||
sh_pushcontext(&sh, &checkpoint, 1);
|
||||
jmpval = sigsetjmp(checkpoint.buff, 0);
|
||||
if(!jmpval)
|
||||
sh_fun(nq,np,(char**)0);
|
||||
sh_popcontext(&sh,&buff);
|
||||
sh_popcontext(&sh, &checkpoint);
|
||||
if(sh.topfd != checkpoint.topfd)
|
||||
sh_iorestore(&sh, checkpoint.topfd, jmpval);
|
||||
unblock(bp,type);
|
||||
if(!vp->disc[type])
|
||||
chktfree(np,vp);
|
||||
|
|
@ -416,6 +434,7 @@ static char* lookup(Namval_t *np, int type, Sfdouble_t *dp,Namfun_t *handle)
|
|||
/* restore everything but the nvlink field */
|
||||
memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
|
||||
}
|
||||
*lexp = savelex;
|
||||
sh.savexit = savexit; /* avoid influencing $? */
|
||||
}
|
||||
if(nv_isarray(np))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue