1
0
mirror of https://github.com/golang/go synced 2024-09-30 12:08:32 -06:00

text/template: fix variadic function call corner case

Executing a template involving variadic functions featuring
a []interface{} slice (such as printf) could result in a
panic in reflect.Value.Call, due to incorrect type checking.

The following expressions failed (with a panic):
{{true|printf}}
{{1|printf}}
{{1.1|printf}}
{{'x'|printf}}
{{1+2i|printf}}

Implemented proper type checks for the fixed parameters of the
variadic functions.

Fixes #10946

Change-Id: Ia75333f651f73b3d2e024cb0c47cc30d90cb6852
Reviewed-on: https://go-review.googlesource.com/10403
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Didier Spezia 2015-05-27 11:44:19 +00:00 committed by Rob Pike
parent f6853369c3
commit 5c60a4fb0a
2 changed files with 26 additions and 1 deletions

View File

@ -581,7 +581,15 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
if final.IsValid() {
t := typ.In(typ.NumIn() - 1)
if typ.IsVariadic() {
t = t.Elem()
if numIn-1 < numFixed {
// The added final argument corresponds to a fixed parameter of the function.
// Validate against the type of the actual parameter.
t = typ.In(numIn - 1)
} else {
// The added final argument corresponds to the variadic part.
// Validate against the type of the elements of the variadic slice.
t = t.Elem()
}
}
argv[i] = s.validateType(final, t)
}

View File

@ -533,6 +533,18 @@ var execTests = []execTest{
{"bug14c", `{{$x := (1.0)}}{{$y := ("hello")}}{{$x.anything}}{{$y.true}}`, "", tVal, false},
// Didn't call validateType on function results. Issue 10800.
{"bug15", "{{valueString returnInt}}", "", tVal, false},
// Variadic function corner cases. Issue 10946.
{"bug16a", "{{true|printf}}", "", tVal, false},
{"bug16b", "{{1|printf}}", "", tVal, false},
{"bug16c", "{{1.1|printf}}", "", tVal, false},
{"bug16d", "{{'x'|printf}}", "", tVal, false},
{"bug16e", "{{0i|printf}}", "", tVal, false},
{"bug16f", "{{true|twoArgs \"xxx\"}}", "", tVal, false},
{"bug16g", "{{\"aaa\" |twoArgs \"bbb\"}}", "twoArgs=bbbaaa", tVal, true},
{"bug16h", "{{1|oneArg}}", "", tVal, false},
{"bug16i", "{{\"aaa\"|oneArg}}", "oneArg=aaa", tVal, true},
{"bug16j", "{{1+2i|printf \"%v\"}}", "(1+2i)", tVal, true},
{"bug16k", "{{\"aaa\"|printf }}", "aaa", tVal, true},
}
func zeroArgs() string {
@ -543,6 +555,10 @@ func oneArg(a string) string {
return "oneArg=" + a
}
func twoArgs(a, b string) string {
return "twoArgs=" + a + b
}
func dddArg(a int, b ...string) string {
return fmt.Sprintln(a, b)
}
@ -620,6 +636,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
"oneArg": oneArg,
"returnInt": returnInt,
"stringer": stringer,
"twoArgs": twoArgs,
"typeOf": typeOf,
"valueString": valueString,
"vfunc": vfunc,