From: Robert Griesemer Date: Sun, 31 Jul 2011 00:11:52 +0000 (-0700) Subject: exp/template: fix endless loop X-Git-Tag: weekly.2011-08-10~60 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7162f39fc322f16624814363f2fc7ca5bad15d4e;p=gostls13.git exp/template: fix endless loop No progress was made in indirect() if the reflect.Value was an non-nil and non-empty interface. R=r, r CC=golang-dev https://golang.org/cl/4810060 --- diff --git a/src/pkg/exp/template/exec.go b/src/pkg/exp/template/exec.go index 40a947dbf0..e500465d12 100644 --- a/src/pkg/exp/template/exec.go +++ b/src/pkg/exp/template/exec.go @@ -585,12 +585,12 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n node) reflect.Value { // We indirect through pointers and empty interfaces (only) because // non-empty interfaces have methods we might need. func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { - for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { + for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { if v.IsNil() { return v, true } - if v.Kind() == reflect.Ptr || v.NumMethod() == 0 { - v = v.Elem() + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break } } return v, false diff --git a/src/pkg/exp/template/exec_test.go b/src/pkg/exp/template/exec_test.go index d9b8afbcd2..ed27e71223 100644 --- a/src/pkg/exp/template/exec_test.go +++ b/src/pkg/exp/template/exec_test.go @@ -75,6 +75,13 @@ var tVal = &T{ Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X } +// A non-empty interface. +type I interface { + Method0() string +} + +var iVal I = tVal + // Helpers for creation. func newInt(n int) *int { p := new(int) @@ -344,6 +351,9 @@ var execTests = []execTest{ // Fixed bugs. // Must separate dot and receiver; otherwise args are evaluated with dot set to variable. {"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true}, + // Do not loop endlessly in indirect for non-empty interfaces. + // The bug appears with *interface only; this is supposed to fail (cannot invoke Method0), but terminate. + {"bug1", "{{.Method0}}", "", &iVal, false}, } func zeroArgs() string {