From b3eabdef52bfab0c23a7884f0d0965aaa830bddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 9 Mar 2019 22:07:59 +0000 Subject: [PATCH] interp: fix using Params as an option to New As correctly pointed out by Marcin Bilski, using the exported function in that way would lead to a panic. And, even after working around the panic, any shell flags used would be overwritten by the first implicit call to Reset. To fix the crash, move the updateExpandOpts method call to the end of the "set" builtin. After all, it's only needed there; the Run function already ends up calling the method later via fillExpandConfig. To keep the shell options from being deleted in Reset, simply whitelist them from the list of fields to clear. We do that for Params, so it follows that the same should happen for the opts field. Finally, add a couple of tests covering both scenarios to TestRunnerOpts. Fixes #365. --- interp/builtin.go | 1 + interp/interp.go | 2 +- interp/interp_test.go | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/interp/builtin.go b/interp/builtin.go index d4a44abb1..0fad50c4e 100644 --- a/interp/builtin.go +++ b/interp/builtin.go @@ -70,6 +70,7 @@ func (r *Runner) builtinCode(ctx context.Context, pos syntax.Pos, name string, a r.errf("set: %v\n", err) return 2 } + r.updateExpandOpts() case "shift": n := 1 switch len(args) { diff --git a/interp/interp.go b/interp/interp.go index d6ec81893..151dab270 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -262,7 +262,6 @@ func Params(args ...string) func(*Runner) error { args = args[1:] } r.Params = args - r.updateExpandOpts() return nil } } @@ -501,6 +500,7 @@ func (r *Runner) Reset() { Exec: r.Exec, Open: r.Open, KillTimeout: r.KillTimeout, + opts: r.opts, // emptied below, to reuse the space Vars: r.Vars, diff --git a/interp/interp_test.go b/interp/interp_test.go index 3bdebbd45..55918325b 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -2743,6 +2743,16 @@ func TestRunnerOpts(t *testing.T) { "[[ $PWD == foo ]]", "exit status 1", }, + { + opts(Params("foo")), + "echo $@", + "foo\n", + }, + { + opts(Params("-u", "--", "foo")), + "echo $@; echo $unset", + "foo\nunset: unbound variable\nexit status 1", + }, } p := syntax.NewParser() for i, c := range cases {