mirror of
https://github.com/golang/go
synced 2024-11-27 05:11:22 -07:00
text/template: add error check for parenthesized first argument in pipeline
An error check was missing: If the first argument of a pipeline is parenthesized, and the pipeline has further arguments, then syntactically the pipeline is a function invocation and there must be a "call". Tricky rare corner case, but easily caught. Add the error check and some tests to verify behavior. Fixes #31810. Change-Id: Ica80b7c11284e4ea9e8cc94a01dbbc9a67e42079 Reviewed-on: https://go-review.googlesource.com/c/go/+/206124 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
b60c7a5c7f
commit
b8cb75fb17
@ -461,7 +461,8 @@ func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final ref
|
||||
// Must be a function.
|
||||
return s.evalFunction(dot, n, cmd, cmd.Args, final)
|
||||
case *parse.PipeNode:
|
||||
// Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
|
||||
// Parenthesized pipeline. The arguments are all inside the pipeline; final must be absent.
|
||||
s.notAFunction(cmd.Args, final)
|
||||
return s.evalPipeline(dot, n)
|
||||
case *parse.VariableNode:
|
||||
return s.evalVariableNode(dot, n, cmd.Args, final)
|
||||
|
@ -352,6 +352,12 @@ var execTests = []execTest{
|
||||
{"field on interface", "{{.foo}}", "<no value>", nil, true},
|
||||
{"field on parenthesized interface", "{{(.).foo}}", "<no value>", nil, true},
|
||||
|
||||
// Issue 31810: Parenthesized first element of pipeline with arguments.
|
||||
// See also TestIssue31810.
|
||||
{"unparenthesized non-function", "{{1 2}}", "", nil, false},
|
||||
{"parenthesized non-function", "{{(1) 2}}", "", nil, false},
|
||||
{"parenthesized non-function with no args", "{{(1)}}", "1", nil, true}, // This is fine.
|
||||
|
||||
// Method calls.
|
||||
{".Method0", "-{{.Method0}}-", "-M0-", tVal, true},
|
||||
{".Method1(1234)", "-{{.Method1 1234}}-", "-1234-", tVal, true},
|
||||
@ -1648,3 +1654,41 @@ func TestExecutePanicDuringCall(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 31810. Check that a parenthesized first argument behaves properly.
|
||||
func TestIssue31810(t *testing.T) {
|
||||
// A simple value with no arguments is fine.
|
||||
var b bytes.Buffer
|
||||
const text = "{{ (.) }}"
|
||||
tmpl, err := New("").Parse(text)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = tmpl.Execute(&b, "result")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if b.String() != "result" {
|
||||
t.Errorf("%s got %q, expected %q", text, b.String(), "result")
|
||||
}
|
||||
|
||||
// Even a plain function fails - need to use call.
|
||||
f := func() string { return "result" }
|
||||
b.Reset()
|
||||
err = tmpl.Execute(&b, f)
|
||||
if err == nil {
|
||||
t.Error("expected error with no call, got none")
|
||||
}
|
||||
|
||||
// Works if the function is explicitly called.
|
||||
const textCall = "{{ (call .) }}"
|
||||
tmpl, err = New("").Parse(textCall)
|
||||
b.Reset()
|
||||
err = tmpl.Execute(&b, f)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if b.String() != "result" {
|
||||
t.Errorf("%s got %q, expected %q", textCall, b.String(), "result")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user