1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix hang in comsubs (rhbz#1062296) (re: 970069a6)

The new command substitution mechanism imported in 970069a6 from
Red Hat patches introduced this bug: backtick-style command
substitutions hang when processing about 117KiB of data or more.

It is fixed by another Red Hat patch:
642af4d6/f/ksh-20140415-hokaido.patch

It saves the value of the shp->comsub flag so that it is set to 2
(usually meaning new-style $(comsubs)) in two specific cases even
when processing backtick comsubs. This stops the sh_subtmpfile()
function in subshell.c from creating a /tmp file. However, I think
that approach is quite ugly, so I'm taking a slightly different one
that has the same effect.

src/cmd/ksh93/include/defs.h,
src/cmd/ksh93/sh/subshell.c:
- Redefine sh_subtmpfile() to pass the comsub flag as an argument.
  (Remove the shp pointer argument, which is redundant; a pointer
  to the shell state can easily be obtained in the function.)

src/cmd/ksh93/sh/xec.c: sh_exec():
- Apply the Red Hat fix by passing flag 2 to sh_subtmpfile().

src/cmd/ksh93/tests/subshell.sh:
- Move regress test from ce68e1be from basic.sh to here; this is
  the place for command substitution tests as they are subshells.
- Add regress test for this bug.

All other changed files:
- Update sh_subtmpfile() calls to pass on the shp->comsub flag.
This commit is contained in:
Martijn Dekker 2020-09-24 05:54:25 +02:00
parent 3654ee73c0
commit 4ce486a7a4
7 changed files with 42 additions and 30 deletions

View file

@ -689,7 +689,7 @@ struct argnod *sh_argprocsub(Shell_t *shp,struct argnod *argp)
ap->argflag &= ~ARG_RAW;
fd = argp->argflag&ARG_RAW;
if(fd==0 && shp->subshell)
sh_subtmpfile(shp);
sh_subtmpfile(shp->comsub);
#if SHOPT_DEVFD
sfwrite(shp->stk,e_devfdNN,8);
pv[2] = 0;

View file

@ -1141,7 +1141,7 @@ int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
if(iof&IOPUT)
ap->argflag = ARG_RAW;
else if(shp->subshell)
sh_subtmpfile(shp);
sh_subtmpfile(shp->comsub);
ap->argchn.ap = (struct argnod*)fname;
ap = sh_argprocsub(shp,ap);
fname = ap->argval;
@ -1203,7 +1203,7 @@ int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
if(shp->subshell && dupfd==1)
{
if(sfset(sfstdout,0,0)&SF_STRING)
sh_subtmpfile(shp);
sh_subtmpfile(shp->comsub);
if(shp->comsub==1)
shp->subdup |= 1<<fn;
dupfd = sffileno(sfstdout);

View file

@ -106,10 +106,11 @@ static unsigned int subenv;
* This routine will turn the sftmp() file into a real /tmp file or pipe
* if the /tmp file create fails
*/
void sh_subtmpfile(Shell_t *shp)
void sh_subtmpfile(char comsub_flag)
{
if(sfset(sfstdout,0,0)&SF_STRING)
{
Shell_t *shp = sh_getinterp();
register int fd;
register struct checkpt *pp = (struct checkpt*)shp->jmplist;
register struct subshell *sp = subshell_data->pipe;
@ -123,7 +124,7 @@ void sh_subtmpfile(Shell_t *shp)
else if(errno!=EBADF)
errormsg(SH_DICT,ERROR_system(1),e_toomany);
/* popping a discipline forces a /tmp file create */
if(shp->comsub != 1)
if(comsub_flag != 1)
sfdisc(sfstdout,SF_POPDISC);
if((fd=sffileno(sfstdout))<0)
{
@ -181,7 +182,7 @@ void sh_subfork(void)
trap = strdup(trap);
/* see whether inside $(...) */
if(sp->pipe)
sh_subtmpfile(shp);
sh_subtmpfile(shp->comsub);
shp->curenv = 0;
shp->savesig = -1;
if(pid = sh_fork(shp,FSHOWME,NIL(int*)))

View file

@ -1319,7 +1319,7 @@ int sh_exec(register const Shnode_t *t, int flags)
bp->notify = 0;
bp->flags = (OPTIMIZE!=0);
if(shp->subshell && nv_isattr(np,BLT_NOSFIO))
sh_subtmpfile(shp);
sh_subtmpfile(shp->comsub);
if(execflg && !shp->subshell &&
!shp->st.trapcom[0] && !shp->st.trap[SH_ERRTRAP] && shp->fn_depth==0 && !nv_isattr(np,BLT_ENV))
{
@ -1527,10 +1527,12 @@ int sh_exec(register const Shnode_t *t, int flags)
int pipes[3];
if(shp->subshell)
{
sh_subtmpfile(shp);
sh_subtmpfile(2);
if(shp->comsub==1 && (!(shp->fdstatus[1]&IONOSEEK)))
unpipe = iousepipe(shp);
if((type&(FAMP|TFORK))==(FAMP|TFORK))
{
if(shp->comsub && !(shp->fdstatus[1]&IONOSEEK))
if(shp->comsub && !(shp->fdstatus[1]&IONOSEEK) && !unpipe)
unpipe = iousepipe(shp);
sh_subfork();
}
@ -1909,7 +1911,7 @@ int sh_exec(register const Shnode_t *t, int flags)
job.curjobid = 0;
if(shp->subshell)
{
sh_subtmpfile(shp);
sh_subtmpfile(2);
if(shp->comsub==1 && !(shp->fdstatus[1]&IONOSEEK))
iousepipe(shp);
}