From: Rob Pike Date: Sat, 15 Feb 2014 00:26:47 +0000 (-0800) Subject: text/template: don't panic when function call evaluates a nil pointer X-Git-Tag: go1.3beta1~688 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=71575a97ab085695e1debd371fb3b33671cd810a;p=gostls13.git text/template: don't panic when function call evaluates a nil pointer Catch the error instead and return it to the user. Before this fix, the template package panicked. Now you get: template: bug11:1:14: executing "bug11" at <.PS>: dereference of nil pointer of type *string Extended example at http://play.golang.org/p/uP6pCW3qKT Fixes #7333. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/64150043 --- diff --git a/src/pkg/text/template/exec.go b/src/pkg/text/template/exec.go index 43b0b266ec..6de37a1996 100644 --- a/src/pkg/text/template/exec.go +++ b/src/pkg/text/template/exec.go @@ -594,6 +594,9 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu switch { case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): value = value.Elem() + if !value.IsValid() { + s.errorf("dereference of nil pointer of type %s", typ) + } case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr(): value = value.Addr() default: diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go index f60702de8f..868f2cb94c 100644 --- a/src/pkg/text/template/exec_test.go +++ b/src/pkg/text/template/exec_test.go @@ -512,6 +512,8 @@ var execTests = []execTest{ {"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true}, // Field chain starting with function did not work. {"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true}, + // Dereferencing nil pointer while evaluating function arguments should not panic. Issue 7333. + {"bug11", "{{valueString .PS}}", "", T{}, false}, } func zeroArgs() string { @@ -546,6 +548,11 @@ func vfunc(V, *V) string { return "vfunc" } +// valueString takes a string, not a pointer. +func valueString(v string) string { + return "value is ignored" +} + func add(args ...int) int { sum := 0 for _, x := range args { @@ -580,17 +587,18 @@ func mapOfThree() interface{} { func testExecute(execTests []execTest, template *Template, t *testing.T) { b := new(bytes.Buffer) funcs := FuncMap{ - "add": add, - "count": count, - "dddArg": dddArg, - "echo": echo, - "makemap": makemap, - "mapOfThree": mapOfThree, - "oneArg": oneArg, - "stringer": stringer, - "typeOf": typeOf, - "vfunc": vfunc, - "zeroArgs": zeroArgs, + "add": add, + "count": count, + "dddArg": dddArg, + "echo": echo, + "makemap": makemap, + "mapOfThree": mapOfThree, + "oneArg": oneArg, + "stringer": stringer, + "typeOf": typeOf, + "valueString": valueString, + "vfunc": vfunc, + "zeroArgs": zeroArgs, } for _, test := range execTests { var tmpl *Template