mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Further fix '<>;' and fix crash on 32-bit systems (re: 6701bb30)
Accessing t->tre.treio for every sh_exec() run is invalid because 't' is of type Shnode_t, which is a union that can contain many different kinds of structs. As all members of a union occupy the same address space, only one can be used at a time. Which member is valid to access depends on the node type sh_exec() was called with. The invalid access triggered a crash on 32-bit systems when executing an arithmetic command like ((x=1)). The t->tre.treio union member should be accessed for a simple command (case TCOM in sh_exec()). The fix is also needed for redirections attached to blocks (case TSETIO) in which case the union member to use is t->fork.forkio. src/cmd/ksh93/sh/xec.c: - Add check_exec_optimization() function that checks for all the conditions where the exec optimisation should not be done. For redirections we need to loop through the whole list to check for an IOREWRITE (<>;) one. - sh_exec(): case TCOM (simple command): Only bother to call check_exec_optimization() if there are either command arguments or redirections (IOW: don't bother for bare variable assignments), so move it to within the if(io||argn) block. - sh_exec(): case TSETIO: This needs a similar fix. To avoid the optimization breaking again if the last command is a subshell with a <>; redirection attached, we need to not only set execflg to 0 but also clear the SH_NOFORK state bit from the 'flags' variable which is passed on to the recursive sh_exec() call. src/cmd/ksh93/tests/io.sh: - Update and expand tests. Add tests for redirections attached to simple commands (TCOM) and various kinds of code block (TSETIO). Co-authored-by: Johnothan King <johnothanking@protonmail.com> Resolves: https://github.com/ksh93/ksh/issues/278
This commit is contained in:
parent
ba43436f10
commit
b0a6c1bde5
3 changed files with 82 additions and 27 deletions
|
|
@ -958,6 +958,21 @@ static Namval_t *enter_namespace(Shell_t *shp, Namval_t *nsp)
|
|||
}
|
||||
#endif /* SHOPT_NAMESPACE */
|
||||
|
||||
/*
|
||||
* Check whether to execve(2) the final command or make its redirections permanent.
|
||||
*/
|
||||
static int check_exec_optimization(struct ionod *iop)
|
||||
{
|
||||
if(sh.subshell || sh.exittrap || sh.errtrap)
|
||||
return(0);
|
||||
/* '<>;' (IOREWRITE) redirections are incompatible with exec */
|
||||
while(iop && !(iop->iofile & IOREWRITE))
|
||||
iop = iop->ionxt;
|
||||
if(iop)
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int sh_exec(register const Shnode_t *t, int flags)
|
||||
{
|
||||
register Shell_t *shp = sh_getinterp();
|
||||
|
|
@ -1003,8 +1018,6 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
shp->exitval=0;
|
||||
shp->lastsig = 0;
|
||||
shp->lastpath = 0;
|
||||
if(shp->exittrap || shp->errtrap || (t->tre.treio && (t->tre.treio->iofile&IOREWRITE)))
|
||||
execflg = 0; /* don't run the command with execve(2) */
|
||||
switch(type&COMMSK)
|
||||
{
|
||||
case TCOM:
|
||||
|
|
@ -1174,6 +1187,8 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
int tflags = 1;
|
||||
if(np && nv_isattr(np,BLT_DCL))
|
||||
tflags |= 2;
|
||||
if(execflg && !check_exec_optimization(io))
|
||||
execflg = 0;
|
||||
if(argn==0)
|
||||
{
|
||||
/* fake 'true' built-in */
|
||||
|
|
@ -1848,8 +1863,6 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
int jmpval, waitall = 0;
|
||||
int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM;
|
||||
struct checkpt *buffp = (struct checkpt*)stkalloc(shp->stk,sizeof(struct checkpt));
|
||||
if(shp->subshell)
|
||||
execflg = 0;
|
||||
sh_pushcontext(shp,buffp,SH_JMPIO);
|
||||
if(type&FPIN)
|
||||
{
|
||||
|
|
@ -1875,6 +1888,11 @@ int sh_exec(register const Shnode_t *t, int flags)
|
|||
{
|
||||
if(shp->comsub==1)
|
||||
tsetio = 1;
|
||||
if(execflg && !check_exec_optimization(t->fork.forkio))
|
||||
{
|
||||
execflg = 0;
|
||||
flags &= ~sh_state(SH_NOFORK);
|
||||
}
|
||||
sh_redirect(shp,t->fork.forkio,execflg);
|
||||
(t->fork.forktre)->tre.tretyp |= t->tre.tretyp&FSHOWME;
|
||||
sh_exec(t->fork.forktre,flags&~simple);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue