Skip to content

Commit

Permalink
Fix I/O redirection in -c script (Solaris patch 280-23332860)
Browse files Browse the repository at this point in the history
This change is pulled from here:
https://github.com/oracle/solaris-userland/blob/master/components/ksh93/patches/280-23332860.patch

Info and reproducers:
att#36

In a -c script (like ksh -c 'commands'), the last command
misredirects standard output if an EXIT or ERR trap is set.
This appears to be a side effect of the optimisation that
runs the last command without forking.

This applies a patch by George Lijo that flags these specific
cases and disables the optimisation.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/bltins/trap.c,
src/cmd/ksh93/sh/init.c,
src/cmd/ksh93/sh/main.c,
src/cmd/ksh93/sh/xec.c:
- Apply patch as above.

src/cmd/ksh93/tests/io.sh:
- Add the reproducers from the bug report as regression tests.
  • Loading branch information
McDutchie committed Jan 8, 2021
1 parent 7c47ab5 commit 17ebfbf
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/cmd/ksh93/bltins/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ int b_trap(int argc,char *argv[],Shbltin_t *context)
shp->trapnote |= SH_SIGTRAP;
else
shp->trapnote = 0;

}
if(sig == SH_ERRTRAP)
{
if(clear)
shp->errtrap = 0;
else if(!shp->fn_depth || shp->end_fn)
shp->errtrap = 1;
}
continue;
}
Expand All @@ -144,6 +152,8 @@ int b_trap(int argc,char *argv[],Shbltin_t *context)
else if(clear)
{
sh_sigclear(sig);
if(sig == 0)
shp->exittrap = 0;
if(dflag)
signal(sig,SIG_DFL);
}
Expand All @@ -156,6 +166,8 @@ int b_trap(int argc,char *argv[],Shbltin_t *context)
shp->st.trapcom[sig] = (shp->sigflag[sig]&SH_SIGOFF) ? Empty : strdup(action);
if(arg && arg != Empty)
free(arg);
if(sig == 0 && (!shp->fn_depth || shp->end_fn))
shp->exittrap = 1;
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/cmd/ksh93/include/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ struct shared
Namfun_t nvfun; \
char *mathnodes; \
char *bltin_dir; \
struct Regress_s*regress;
struct Regress_s*regress; \
char exittrap; \
char errtrap; \
char end_fn;

#include <shell.h>

Expand Down
6 changes: 6 additions & 0 deletions src/cmd/ksh93/sh/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,9 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit)
#endif
if(shp->userinit=userinit)
(*userinit)(shp, 0);
shp->exittrap = 0;
shp->errtrap = 0;
shp->end_fn = 0;
return(shp);
}

Expand Down Expand Up @@ -1580,6 +1583,9 @@ int sh_reinit(char *argv[])
shp->inpipe = shp->outpipe = 0;
job_clear();
job.in_critical = 0;
shp->exittrap = 0;
shp->errtrap = 0;
shp->end_fn = 0;
/* update ${.sh.pid}, $$, $PPID */
shgd->current_pid = shgd->pid = getpid();
shgd->ppid = getppid();
Expand Down
3 changes: 3 additions & 0 deletions src/cmd/ksh93/sh/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,9 @@ static void exfile(register Shell_t *shp, register Sfio_t *iop,register int fno)
error_info.line = 1;
shp->inlineno = 1;
shp->binscript = 0;
shp->exittrap = 0;
shp->errtrap = 0;
shp->end_fn = 0;
if(sfeof(iop))
goto eof_or_error;
/* command loop */
Expand Down
5 changes: 5 additions & 0 deletions src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,8 @@ int sh_exec(register const Shnode_t *t, int flags)
shp->exitval=0;
shp->lastsig = 0;
shp->lastpath = 0;
if(shp->exittrap || shp->errtrap)
execflg = 0;
switch(type&COMMSK)
{
case TCOM:
Expand Down Expand Up @@ -3119,6 +3121,8 @@ int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
nv_putval(SH_PATHNAMENOD,shp->st.filename,NV_NOFREE);
nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
}
if((execflg & sh_state(SH_NOFORK)))
shp->end_fn = 1;
jmpval = sigsetjmp(buffp->buff,0);
if(jmpval == 0)
{
Expand Down Expand Up @@ -3166,6 +3170,7 @@ int sh_funscope(int argn, char *argv[],int(*fun)(void*),void *arg,int execflg)
shp->st = *prevscope;
shp->topscope = (Shscope_t*)prevscope;
nv_getval(sh_scoped(shp,IFSNOD));
shp->end_fn = 0;
if(nsig)
{
for (isig = 0; isig < nsig; ++isig)
Expand Down
48 changes: 48 additions & 0 deletions src/cmd/ksh93/tests/io.sh
Original file line number Diff line number Diff line change
Expand Up @@ -649,5 +649,53 @@ err=$(
((!(e = $?))) || err_exit 'crash on null-command redirection with DEBUG trap' \
"(got status $e$( ((e>128)) && print -n / && kill -l "$e"), $(printf %q "$got"))"
# ======
# stdout was misdirected if an EXIT/ERR trap handler was defined in a -c script
# https://github.com/att/ast/issues/36
exp=$'exit to stdout\ntrap to stdout'
exp2=$'exit to file\ntrap to file'
got=$(export tmp; "$SHELL" -ec \
' function log
{
echo "$* to stdout"
echo "$* to file" >> $tmp/ast36_a.test.log
}
function test_exit
{
log trap
}
trap test_exit EXIT
log exit
')
[[ $got == "$exp" ]] || err_exit 'stdout misdirected to file with EXIT/ERR trap defined (1)' \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
[[ $(< $tmp/ast36_a.test.log) == "$exp2" ]] || err_exit 'stdout not correctly redirected to file with EXIT/ERR trap defined (1)' \
"(expected $(printf %q "$exp2"), wrote $(printf %q "$(< $tmp/ast36_a.test.log)"))"
exp=$'trap to stdout\nexit to stdout'
exp2=$'trap to file\nexit to file'
got=$(export tmp; "$SHELL" -ec \
' function log
{
echo "$* to stdout"
echo "$* to file" >> $tmp/ast36_b.test.log
}
function test_exit
{
trap test_exittrap EXIT
log trap
}
function test_exittrap
{
log exit
}
test_exit
')
[[ $got == "$exp" ]] || err_exit 'stdout misdirected to file with EXIT/ERR trap defined (2)' \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
[[ $(< $tmp/ast36_b.test.log) == "$exp2" ]] || err_exit 'stdout not correctly redirected to file with EXIT/ERR trap defined (2)' \
"(expected $(printf %q "$exp2"), wrote $(printf %q "$(< $tmp/ast36_b.test.log)"))"
# ======
exit $((Errors<125?Errors:125))

0 comments on commit 17ebfbf

Please sign in to comment.