From 13aa235ae0b441989f6ac3cb5ea953836dcdfdde Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Fri, 30 Nov 2018 09:50:05 -0500 Subject: [PATCH] go/internal/gccgoimporter: fix bug reading V1 export data Fix a bug in the reading of elderly export data. In such export data when reading type information it's possible to encounter a named type N1 defined as a typedef of some other named type N2 at a point when the underying type of N1 has not yet been finalized. Handle this case by generating a fixup, then process fixups at the end of parsing to set the correct underlying type. Fixes #29006. Change-Id: I6a505c897bd95eb161ee04637bb6eebad9f20d52 Reviewed-on: https://go-review.googlesource.com/c/151997 Run-TryBot: Than McIntosh Reviewed-by: Robert Griesemer TryBot-Result: Gobot Gobot --- .../internal/gccgoimporter/importer_test.go | 1 + src/go/internal/gccgoimporter/parser.go | 38 +++++++++++++++++- .../gccgoimporter/testdata/v1reflect.gox | Bin 0 -> 10872 bytes 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/go/internal/gccgoimporter/testdata/v1reflect.gox diff --git a/src/go/internal/gccgoimporter/importer_test.go b/src/go/internal/gccgoimporter/importer_test.go index 96505b2bab..30b51db9d4 100644 --- a/src/go/internal/gccgoimporter/importer_test.go +++ b/src/go/internal/gccgoimporter/importer_test.go @@ -86,6 +86,7 @@ var importerTests = [...]importerTest{ {pkgpath: "aliases", name: "C0", want: "type C0 struct{f1 C1; f2 C1}"}, {pkgpath: "escapeinfo", name: "NewT", want: "func NewT(data []byte) *T"}, {pkgpath: "issue27856", name: "M", want: "type M struct{E F}"}, + {pkgpath: "v1reflect", name: "Type", want: "type Type interface{Align() int; AssignableTo(u Type) bool; Bits() int; ChanDir() ChanDir; Elem() Type; Field(i int) StructField; FieldAlign() int; FieldByIndex(index []int) StructField; FieldByName(name string) (StructField, bool); FieldByNameFunc(match func(string) bool) (StructField, bool); Implements(u Type) bool; In(i int) Type; IsVariadic() bool; Key() Type; Kind() Kind; Len() int; Method(int) Method; MethodByName(string) (Method, bool); Name() string; NumField() int; NumIn() int; NumMethod() int; NumOut() int; Out(i int) Type; PkgPath() string; Size() uintptr; String() string; common() *commonType; rawString() string; runtimeType() *runtimeType; uncommon() *uncommonType}"}, } func TestGoxImporter(t *testing.T) { diff --git a/src/go/internal/gccgoimporter/parser.go b/src/go/internal/gccgoimporter/parser.go index e75f15c429..7d075db4ce 100644 --- a/src/go/internal/gccgoimporter/parser.go +++ b/src/go/internal/gccgoimporter/parser.go @@ -29,9 +29,30 @@ type parser struct { imports map[string]*types.Package // package path -> package object typeList []types.Type // type number -> type typeData []string // unparsed type data (v3 and later) + fixups []fixupRecord // fixups to apply at end of parsing initdata InitData // package init priority data } +// When reading V1 export data it's possible to encounter a defined +// type N1 with an underlying defined type N2 while we are still +// reading in that defined type N2; see issue #29006 for an instance +// of this. Example: +// +// type N1 N2 +// type N2 struct { +// ... +// p *N1 +// } +// +// To handle such cases, the parser generates a fixup record (below) and +// delays setting of N1's underlying type until parsing is complete, at +// which point fixups are applied. + +type fixupRecord struct { + toUpdate *types.Named // type to modify when fixup is processed + target types.Type // type that was incomplete when fixup was created +} + func (p *parser) init(filename string, src io.Reader, imports map[string]*types.Package) { p.scanner = new(scanner.Scanner) p.initScanner(filename, src) @@ -504,7 +525,15 @@ func (p *parser) parseNamedType(nlist []int) types.Type { underlying := p.parseType(pkg) if nt.Underlying() == nil { - nt.SetUnderlying(underlying.Underlying()) + if underlying.Underlying() == nil { + if p.version != "v1" { + p.errorf("internal error: unexpected fixup required for %v", nt) + } + fix := fixupRecord{toUpdate: nt, target: underlying} + p.fixups = append(p.fixups, fix) + } else { + nt.SetUnderlying(underlying.Underlying()) + } } if p.tok == '\n' { @@ -1175,6 +1204,13 @@ func (p *parser) parsePackage() *types.Package { for p.tok != scanner.EOF { p.parseDirective() } + for _, f := range p.fixups { + if f.target.Underlying() == nil { + p.errorf("internal error: fixup can't be applied, loop required") + } + f.toUpdate.SetUnderlying(f.target.Underlying()) + } + p.fixups = nil for _, typ := range p.typeList { if it, ok := typ.(*types.Interface); ok { it.Complete() diff --git a/src/go/internal/gccgoimporter/testdata/v1reflect.gox b/src/go/internal/gccgoimporter/testdata/v1reflect.gox new file mode 100644 index 0000000000000000000000000000000000000000..ea468414d9fa8ad66e978799a8ff5d2f90eb4961 GIT binary patch literal 10872 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 BTEYMT literal 0 HcmV?d00001 -- 2.50.0