Commit 71575a97 authored by Rob Pike's avatar Rob Pike

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
parent 881e23d3
...@@ -594,6 +594,9 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu ...@@ -594,6 +594,9 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
switch { switch {
case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
value = value.Elem() 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(): case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
value = value.Addr() value = value.Addr()
default: default:
......
...@@ -512,6 +512,8 @@ var execTests = []execTest{ ...@@ -512,6 +512,8 @@ var execTests = []execTest{
{"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true}, {"bug9", "{{.cause}}", "neglect", map[string]string{"cause": "neglect"}, true},
// Field chain starting with function did not work. // Field chain starting with function did not work.
{"bug10", "{{mapOfThree.three}}-{{(mapOfThree).three}}", "3-3", 0, true}, {"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 { func zeroArgs() string {
...@@ -546,6 +548,11 @@ func vfunc(V, *V) string { ...@@ -546,6 +548,11 @@ func vfunc(V, *V) string {
return "vfunc" return "vfunc"
} }
// valueString takes a string, not a pointer.
func valueString(v string) string {
return "value is ignored"
}
func add(args ...int) int { func add(args ...int) int {
sum := 0 sum := 0
for _, x := range args { for _, x := range args {
...@@ -589,6 +596,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) { ...@@ -589,6 +596,7 @@ func testExecute(execTests []execTest, template *Template, t *testing.T) {
"oneArg": oneArg, "oneArg": oneArg,
"stringer": stringer, "stringer": stringer,
"typeOf": typeOf, "typeOf": typeOf,
"valueString": valueString,
"vfunc": vfunc, "vfunc": vfunc,
"zeroArgs": zeroArgs, "zeroArgs": zeroArgs,
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment