diff --git a/staticcheck/fakexml/typeinfo.go b/staticcheck/fakexml/typeinfo.go index bf5c73bf..3e3ecbae 100644 --- a/staticcheck/fakexml/typeinfo.go +++ b/staticcheck/fakexml/typeinfo.go @@ -75,9 +75,19 @@ var tinfoMap sync.Map // map[reflect.Type]*typeInfo // getTypeInfo returns the typeInfo structure with details necessary // for marshaling and unmarshaling typ. func getTypeInfo(typ fakereflect.TypeAndCanAddr) (*typeInfo, error) { + return getTypeInfoRecursive(typ, map[fakereflect.TypeAndCanAddr]bool{}) +} + +func getTypeInfoRecursive(typ fakereflect.TypeAndCanAddr, visiting map[fakereflect.TypeAndCanAddr]bool) (*typeInfo, error) { if ti, ok := tinfoMap.Load(typ); ok { return ti.(*typeInfo), nil } + if visiting[typ] { + // Recursive embedded structs cannot contribute fields indefinitely. + return &typeInfo{}, nil + } + visiting[typ] = true + defer delete(visiting, typ) tinfo := &typeInfo{} if typ.IsStruct() && !typeutil.IsTypeWithName(typ.Type, "encoding/xml.Name") { @@ -95,7 +105,7 @@ func getTypeInfo(typ fakereflect.TypeAndCanAddr) (*typeInfo, error) { t = t.Elem() } if t.IsStruct() { - inner, err := getTypeInfo(t) + inner, err := getTypeInfoRecursive(t, visiting) if err != nil { return nil, err } diff --git a/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go b/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go index 2ae94692..dc9aa3aa 100644 --- a/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go +++ b/staticcheck/sa1026/testdata/go1.0/CheckUnsupportedMarshal/CheckUnsupportedMarshal.go @@ -57,6 +57,10 @@ type Recursive struct { Field *Recursive } +type RecursiveEmbed struct { + *RecursiveEmbed +} + type ValueMarshaler chan int func (ValueMarshaler) MarshalText() ([]byte, error) { return nil, nil } @@ -316,6 +320,11 @@ func cyclicPointer() { xml.Marshal(s) //@ diag(`cyclic type P, via x.Foo.Bar`) } +func cyclicEmbeddedStruct() { + var value RecursiveEmbed + xml.Marshal(value) +} + func functionAsArgument(arg T1) { // https://staticcheck.io/issues/1660