diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2020-05-27 13:19:10 +1000 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2020-06-01 23:28:36 +1000 |
commit | d80189f2b99a4172a60589b6c23eedc2b4077a20 (patch) | |
tree | 29af946fa09ffabbe01bfb2d96dea3b13fb79c08 | |
parent | 8557066bcf8d76734331051cfbcdd9ba6cbb730f (diff) | |
download | dash-d80189f2b99a4172a60589b6c23eedc2b4077a20.tar.gz |
eval: Prevent recursive PS4 expansion
Yaroslav Halchenko <yoh@onerussian.com> wrote:
>
> I like to (ab)use PS4 and set -x for tracing execution of scripts.
> Reporting time and PID is very useful in this context.
>
> I am not 100% certain if bash's behavior (of actually running the command
> embedded within PS4 string, probably eval'ing it) is actually POSIX
> compliant, posh seems to not do that; but I think it is definitely not
> desired for dash to just stall:
>
> - the script:
>
> #!/bin/sh
> set -x
> export PS4='+ $(date +%T.%N) [$$] '
>
> echo "lets go"
> sleep 1
> echo "done $var"
>
> - bash:
>
> /tmp > bash --posix test.sh
> +export 'PS4=+ $(date +%T.%N) [$$] '
> +PS4='+ $(date +%T.%N) [$$] '
> + 09:15:48.982296333 [2764323] echo 'lets go'
> lets go
> + 09:15:48.987829613 [2764323] sleep 1
> + 09:15:49.994485037 [2764323] echo 'done '
> done
>
>
> - posh:
> exit:130 /tmp > posh test.sh
> +export PS4=+ $(date +%T.%N) [$$]
> + $(date +%T.%N) [$$] echo lets go
> lets go
> + $(date +%T.%N) [$$] sleep 1
> + $(date +%T.%N) [$$] echo done
> done
>
> - dash: (stalls it set -x)
>
> /tmp > dash test.sh
> +export PS4=+ $(date +%T.%N) [$$]
> ^C^C
This patch fixes the infinite loop caused by repeated expansions
of PS4.
Reported-by: Yaroslav Halchenko <yoh@onerussian.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | src/eval.c | 8 |
1 files changed, 7 insertions, 1 deletions
@@ -78,6 +78,9 @@ int exitstatus; /* exit status of last command */ int back_exitstatus; /* exit status of backquoted command */ int savestatus = -1; /* exit status of last command outside traps */ +/* Prevent PS4 nesting. */ +MKINIT int inps4; + #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3) STATIC @@ -123,6 +126,7 @@ EXITRESET { } evalskip = 0; loopnest = 0; + inps4 = 0; } #endif @@ -855,12 +859,14 @@ bail: } /* Print the command if xflag is set. */ - if (xflag) { + if (xflag && !inps4) { struct output *out; int sep; out = &preverrout; + inps4 = 1; outstr(expandstr(ps4val()), out); + inps4 = 0; sep = 0; sep = eprintlist(out, varlist.list, sep); eprintlist(out, osp, sep); |