1
0
Fork 0
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:
Martijn Dekker 2021-04-17 21:31:38 +01:00
parent ba43436f10
commit b0a6c1bde5
3 changed files with 82 additions and 27 deletions

View file

@ -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);