]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: use reflect.Value.FieldByIndexErr
authorRob Pike <r@golang.org>
Sun, 24 Oct 2021 04:44:15 +0000 (15:44 +1100)
committerRob Pike <r@golang.org>
Fri, 29 Oct 2021 02:12:05 +0000 (02:12 +0000)
to avoid a crash on a nil pointer as an embedded field.

Fixes #48215

Change-Id: I214faa6e3cf08cdec1c01035e4bbca0900c6a408
Reviewed-on: https://go-review.googlesource.com/c/go/+/357963
Trust: Rob Pike <r@golang.org>
Run-TryBot: Rob Pike <r@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/text/template/exec.go
src/text/template/exec_test.go

index 7e44497530888b8d1e8d0fe61fcc045577c39531..c42cbb2ad3030dbea199f14b21d72ac3620b0e03 100644 (file)
@@ -635,10 +635,13 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
        case reflect.Struct:
                tField, ok := receiver.Type().FieldByName(fieldName)
                if ok {
-                       field := receiver.FieldByIndex(tField.Index)
+                       field, err := receiver.FieldByIndexErr(tField.Index)
                        if !tField.IsExported() {
                                s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
                        }
+                       if err != nil {
+                               s.errorf("%v", err)
+                       }
                        // If it's a function, we must call it.
                        if hasArgs {
                                s.errorf("%s has arguments but cannot be invoked as function", fieldName)
index 9c0772945e845428df8f7d980cfb2be27d226f99..3c40aa901e19ec3007c8967bc6c1381a13a9849c 100644 (file)
@@ -1787,3 +1787,26 @@ func TestIssue39807(t *testing.T) {
 
        wg.Wait()
 }
+
+// Issue 48215: embedded nil pointer causes panic.
+// Fixed by adding FieldByIndexErr to the reflect package.
+func TestIssue48215(t *testing.T) {
+       type A struct {
+               S string
+       }
+       type B struct {
+               *A
+       }
+       tmpl, err := New("").Parse(`{{ .S }}`)
+       if err != nil {
+               t.Fatal(err)
+       }
+       err = tmpl.Execute(io.Discard, B{})
+       // We expect an error, not a panic.
+       if err == nil {
+               t.Fatal("did not get error for nil embedded struct")
+       }
+       if !strings.Contains(err.Error(), "reflect: indirection through nil pointer to embedded struct field A") {
+               t.Fatal(err)
+       }
+}