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
|
@ -669,6 +669,8 @@ make install
|
||||||
done main.o generated
|
done main.o generated
|
||||||
make nvdisc.o
|
make nvdisc.o
|
||||||
make sh/nvdisc.c
|
make sh/nvdisc.c
|
||||||
|
prev include/shlex.h implicit
|
||||||
|
prev include/io.h implicit
|
||||||
prev include/path.h implicit
|
prev include/path.h implicit
|
||||||
prev include/builtins.h implicit
|
prev include/builtins.h implicit
|
||||||
prev include/variables.h implicit
|
prev include/variables.h implicit
|
||||||
|
|
|
@ -2186,8 +2186,15 @@ static int io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
case 2:
|
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));
|
cp = nv_getval(sh_scoped(shp,PS2NOD));
|
||||||
|
stakset(savestackptr, savestacktop);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 3:
|
case 3:
|
||||||
cp = nv_getval(sh_scoped(shp,PS3NOD));
|
cp = nv_getval(sh_scoped(shp,PS3NOD));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "shlex.h"
|
||||||
|
|
||||||
static void assign(Namval_t*,const char*,int,Namfun_t*);
|
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];
|
nq = vp->disc[type=UNASSIGN];
|
||||||
if(nq && !isblocked(bp,type))
|
if(nq && !isblocked(bp,type))
|
||||||
{
|
{
|
||||||
int bflag=0, savexit=sh.savexit, jmpval=0;
|
struct checkpt checkpoint;
|
||||||
struct checkpt buff;
|
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);
|
block(bp,type);
|
||||||
if (type==APPEND && (bflag= !isblocked(bp,LOOKUPS)))
|
if(bflag = (type==APPEND && !isblocked(bp,LOOKUPS)))
|
||||||
block(bp,LOOKUPS);
|
block(bp,LOOKUPS);
|
||||||
sh_pushcontext(&sh,&buff,1);
|
sh_pushcontext(&sh, &checkpoint, 1);
|
||||||
jmpval = sigsetjmp(buff.buff,0);
|
jmpval = sigsetjmp(checkpoint.buff, 0);
|
||||||
if(!jmpval)
|
if(!jmpval)
|
||||||
sh_fun(nq,np,(char**)0);
|
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);
|
unblock(bp,type);
|
||||||
if(bflag)
|
if(bflag)
|
||||||
unblock(bp,LOOKUPS);
|
unblock(bp,LOOKUPS);
|
||||||
if(!vp->disc[type])
|
if(!vp->disc[type])
|
||||||
chktfree(np,vp);
|
chktfree(np,vp);
|
||||||
|
*lexp = savelex;
|
||||||
sh.savexit = savexit; /* avoid influencing $? */
|
sh.savexit = savexit; /* avoid influencing $? */
|
||||||
}
|
}
|
||||||
if(nv_isarray(np))
|
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;
|
union Value *up = np->nvalue.up;
|
||||||
if(nq && !isblocked(bp,type))
|
if(nq && !isblocked(bp,type))
|
||||||
{
|
{
|
||||||
int savexit = sh.savexit, jmpval = 0;
|
struct checkpt checkpoint;
|
||||||
struct checkpt buff;
|
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;
|
node = *SH_VALNOD;
|
||||||
if(!nv_isnull(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);
|
nv_setsize(SH_VALNOD,10);
|
||||||
}
|
}
|
||||||
block(bp,type);
|
block(bp,type);
|
||||||
sh_pushcontext(&sh,&buff,1);
|
sh_pushcontext(&sh, &checkpoint, 1);
|
||||||
jmpval = sigsetjmp(buff.buff,0);
|
jmpval = sigsetjmp(checkpoint.buff, 0);
|
||||||
if(!jmpval)
|
if(!jmpval)
|
||||||
sh_fun(nq,np,(char**)0);
|
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);
|
unblock(bp,type);
|
||||||
if(!vp->disc[type])
|
if(!vp->disc[type])
|
||||||
chktfree(np,vp);
|
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 */
|
/* restore everything but the nvlink field */
|
||||||
memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
|
memcpy(&SH_VALNOD->nvname, &node.nvname, sizeof(node)-sizeof(node.nvlink));
|
||||||
}
|
}
|
||||||
|
*lexp = savelex;
|
||||||
sh.savexit = savexit; /* avoid influencing $? */
|
sh.savexit = savexit; /* avoid influencing $? */
|
||||||
}
|
}
|
||||||
if(nv_isarray(np))
|
if(nv_isarray(np))
|
||||||
|
|
|
@ -889,5 +889,27 @@ w true); echo "Exit status is $?"
|
||||||
u Exit status is 0
|
u Exit status is 0
|
||||||
!
|
!
|
||||||
|
|
||||||
|
# err_exit #
|
||||||
|
tst $LINENO <<"!"
|
||||||
|
L interrupted PS2 discipline function
|
||||||
|
# https://github.com/ksh93/ksh/issues/347
|
||||||
|
|
||||||
|
d 15
|
||||||
|
p :test-1:
|
||||||
|
w PS2.get() { trap --bad-option 2>/dev/null; .sh.value="NOT REACHED"; }
|
||||||
|
p :test-2:
|
||||||
|
w echo \$\(
|
||||||
|
r :test-2: echo \$\(
|
||||||
|
w echo one \\
|
||||||
|
r > echo one \\
|
||||||
|
w two three
|
||||||
|
r > two three
|
||||||
|
w echo end
|
||||||
|
r > echo end
|
||||||
|
w \)
|
||||||
|
r > \)
|
||||||
|
r one two three end
|
||||||
|
!
|
||||||
|
|
||||||
# ======
|
# ======
|
||||||
exit $((Errors<125?Errors:125))
|
exit $((Errors<125?Errors:125))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue