diff options
author | jilles <jilles@FreeBSD.org> | 2017-03-12 18:38:03 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2017-03-12 18:38:03 +0000 |
commit | fad9bc33a21dea59b9141f4c4a818b8da7940f02 (patch) | |
tree | 241f1c36998f139d25db6d4ca988e49053996a94 /bin | |
parent | c52ab07b68286c4c43d14217015a2fc847019e99 (diff) | |
download | FreeBSD-src-fad9bc33a21dea59b9141f4c4a818b8da7940f02.zip FreeBSD-src-fad9bc33a21dea59b9141f4c4a818b8da7940f02.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.
Reported by: bdrewery
Diffstat (limited to 'bin')
-rw-r--r-- | bin/sh/expand.c | 7 | ||||
-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, 19 insertions, 2 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c index fe72c49..8de5141 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -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; @@ -513,12 +512,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; } diff --git a/bin/sh/tests/expansion/Makefile b/bin/sh/tests/expansion/Makefile index 3c0dfa3..c062232 100644 --- a/bin/sh/tests/expansion/Makefile +++ b/bin/sh/tests/expansion/Makefile @@ -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 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 ] |