sh: Fix crash if a -T trap is taken during command substitution.

Code like  t=$(stat -f %m "$file")  segfaulted if -T was active and a trap
was taken while the shell was waiting for the child process to finish.

What happened was that the dotrap() call in waitforjob() was hit. This
re-entered command execution (including expand.c) at a point not expected by
expbackq(), and global state (unallocated stack string and argbackq) was
corrupted.

To fix this, change expbackq() to prepare for command execution to be
re-entered.

Reported by:	bdrewery
MFC after:	1 week
This commit is contained in:
Jilles Tjoelker 2017-03-04 22:58:34 +00:00
parent 9c4241c3d7
commit 586fd24857
4 changed files with 19 additions and 2 deletions

View File

@ -460,7 +460,6 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst)
p = grabstackstr(dest);
evalbackcmd(cmd, &in);
ungrabstackstr(p, dest);
argbackq = saveargbackq;
p = in.buf;
nnl = 0;
@ -514,12 +513,16 @@ expbackq(union node *cmd, int quoted, int flag, struct worddest *dst)
close(in.fd);
if (in.buf)
ckfree(in.buf);
if (in.jp)
if (in.jp) {
p = grabstackstr(dest);
exitstatus = waitforjob(in.jp, (int *)NULL);
ungrabstackstr(p, dest);
}
TRACE(("expbackq: size=%td: \"%.*s\"\n",
((dest - stackblock()) - startloc),
(int)((dest - stackblock()) - startloc),
stackblock() + startloc));
argbackq = saveargbackq;
expdest = dest;
INTON;
}

View File

@ -42,6 +42,8 @@ ${PACKAGE}FILES+= cmdsubst17.0
${PACKAGE}FILES+= cmdsubst18.0
${PACKAGE}FILES+= cmdsubst19.0
${PACKAGE}FILES+= cmdsubst20.0
${PACKAGE}FILES+= cmdsubst21.0
${PACKAGE}FILES+= cmdsubst22.0
${PACKAGE}FILES+= export1.0
${PACKAGE}FILES+= export2.0
${PACKAGE}FILES+= export3.0

View File

@ -0,0 +1,6 @@
# $FreeBSD$
set -T
trapped=''
trap "trapped=x$trapped" TERM
[ "x$($SH -c "kill $$")y" = xy ] && [ "$trapped" = x ]

View File

@ -0,0 +1,6 @@
# $FreeBSD$
set -T
trapped=''
trap "trapped=x$trapped" TERM
[ "x$(:; kill $$)y" = xy ] && [ "$trapped" = x ]