diff options
author | jilles <jilles@FreeBSD.org> | 2017-04-14 21:42:27 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2017-04-14 21:42:27 +0000 |
commit | a6ea2c942b8e88b6588058e30887ff2d28124f0f (patch) | |
tree | c1a8beacfa38020164c873fabbbe33852d3c0fcd /bin | |
parent | 77ad58ffd42cd8728b0dca6e517dcb3835736837 (diff) | |
download | FreeBSD-src-a6ea2c942b8e88b6588058e30887ff2d28124f0f.zip FreeBSD-src-a6ea2c942b8e88b6588058e30887ff2d28124f0f.tar.gz |
MFC r314686: 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.
In stable/10, there is more global state that needs to be restored than in
stable/11 and head.
Reported by: bdrewery
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/expand.c | 15 | ||||
-rw-r--r-- | bin/sh/tests/expansion/Makefile | 2 | ||||
-rw-r--r-- | bin/sh/tests/expansion/cmdsubst21.0 | 6 | ||||
-rw-r--r-- | bin/sh/tests/expansion/cmdsubst22.0 | 6 |
4 files changed, 23 insertions, 6 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 2113ab7..f61c10b 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -439,9 +439,6 @@ expbackq(union node *cmd, int quoted, int flag) p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); - ifsfirst = saveifs; - ifslastp = savelastp; - argbackq = saveargbackq; p = in.buf; lastc = '\0'; @@ -479,14 +476,20 @@ expbackq(union node *cmd, int quoted, int flag) close(in.fd); if (in.buf) ckfree(in.buf); - if (in.jp) + if (in.jp) { + p = grabstackstr(dest); exitstatus = waitforjob(in.jp, (int *)NULL); - if (quoted == 0) - recordregion(startloc, dest - stackblock(), 0); + ungrabstackstr(p, dest); + } TRACE(("expbackq: size=%td: \"%.*s\"\n", ((dest - stackblock()) - startloc), (int)((dest - stackblock()) - startloc), stackblock() + startloc)); + ifsfirst = saveifs; + ifslastp = savelastp; + if (quoted == 0) + recordregion(startloc, dest - stackblock(), 0); + argbackq = saveargbackq; expdest = dest; INTON; } diff --git a/bin/sh/tests/expansion/Makefile b/bin/sh/tests/expansion/Makefile index fd1c3bb..ecf1084 100644 --- a/bin/sh/tests/expansion/Makefile +++ b/bin/sh/tests/expansion/Makefile @@ -41,6 +41,8 @@ FILES+= cmdsubst17.0 FILES+= cmdsubst18.0 FILES+= cmdsubst19.0 FILES+= cmdsubst20.0 +FILES+= cmdsubst21.0 +FILES+= cmdsubst22.0 FILES+= export1.0 FILES+= export2.0 FILES+= export3.0 diff --git a/bin/sh/tests/expansion/cmdsubst21.0 b/bin/sh/tests/expansion/cmdsubst21.0 new file mode 100644 index 0000000..87ff6a9 --- /dev/null +++ b/bin/sh/tests/expansion/cmdsubst21.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +set -T +trapped='' +trap "trapped=x$trapped" TERM +[ "x$($SH -c "kill $$")y" = xy ] && [ "$trapped" = x ] diff --git a/bin/sh/tests/expansion/cmdsubst22.0 b/bin/sh/tests/expansion/cmdsubst22.0 new file mode 100644 index 0000000..97c6c98 --- /dev/null +++ b/bin/sh/tests/expansion/cmdsubst22.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +set -T +trapped='' +trap "trapped=x$trapped" TERM +[ "x$(:; kill $$)y" = xy ] && [ "$trapped" = x ] |