Skip to content

Commit 5c60a4f

Browse files
dspeziarobpike
authored andcommitted
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 <[email protected]>
1 parent f685336 commit 5c60a4f

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/text/template/exec.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,15 @@ func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, a
581581
if final.IsValid() {
582582
t := typ.In(typ.NumIn() - 1)
583583
if typ.IsVariadic() {
584-
t = t.Elem()
584+
if numIn-1 < numFixed {
585+
// The added final argument corresponds to a fixed parameter of the function.
586+
// Validate against the type of the actual parameter.
587+
t = typ.In(numIn - 1)
588+
} else {
589+
// The added final argument corresponds to the variadic part.
590+
// Validate against the type of the elements of the variadic slice.
591+
t = t.Elem()
592+
}
585593
}
586594
argv[i] = s.validateType(final, t)
587595
}

src/text/template/exec_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,18 @@ var execTests = []execTest{
533533
{"bug14c", `{{$x := (1.0)}}{{$y := ("hello")}}{{$x.anything}}{{$y.true}}`, "", tVal, false},
534534
// Didn't call validateType on function results. Issue 10800.
535535
{"bug15", "{{valueString returnInt}}", "", tVal, false},
536+
// Variadic function corner cases. Issue 10946.
537+
{"bug16a", "{{true|printf}}", "", tVal, false},
538+
{"bug16b", "{{1|printf}}", "", tVal, false},
539+
{"bug16c", "{{1.1|printf}}", "", tVal, false},
540+
{"bug16d", "{{'x'|printf}}", "", tVal, false},
541+
{"bug16e", "{{0i|printf}}", "", tVal, false},
542+
{"bug16f", "{{true|twoArgs \"xxx\"}}", "", tVal, false},
543+
{"bug16g", "{{\"aaa\" |twoArgs \"bbb\"}}", "twoArgs=bbbaaa", tVal, true},
544+
{"bug16h", "{{1|oneArg}}", "", tVal, false},
545+
{"bug16i", "{{\"aaa\"|oneArg}}", "oneArg=aaa", tVal, true},
546+
{"bug16j", "{{1+2i|printf \"%v\"}}", "(1+2i)", tVal, true},
547+
{"bug16k", "{{\"aaa\"|printf }}", "aaa", tVal, true},
536548
}
537549

538550
func zeroArgs() string {
@@ -543,6 +555,10 @@ func oneArg(a string) string {
543555
return "oneArg=" + a
544556
}
545557

558+
func twoArgs(a, b string) string {
559+
return "twoArgs=" + a + b
560+
}
561+
546562
func dddArg(a int, b ...string) string {
547563
return fmt.Sprintln(a, b)
548564
}
@@ -620,6 +636,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
620636
"oneArg": oneArg,
621637
"returnInt": returnInt,
622638
"stringer": stringer,
639+
"twoArgs": twoArgs,
623640
"typeOf": typeOf,
624641
"valueString": valueString,
625642
"vfunc": vfunc,

0 commit comments

Comments
 (0)