1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:04:40 -07:00

cmd/cgo: avoid endless recursion on recursive type

Fixes #69176

Change-Id: I2e3b2a7cf7699697b957fc69ecf5200ebb137bc3
Reviewed-on: https://go-review.googlesource.com/c/go/+/609975
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Ian Lance Taylor 2024-08-30 15:44:02 -07:00 committed by Gopher Robot
parent 065c1359e1
commit f22afc5844
3 changed files with 29 additions and 2 deletions

View File

@ -132,6 +132,7 @@ func TestReportsTypeErrors(t *testing.T) {
"issue50710.go",
"issue67517.go",
"issue67707.go",
"issue69176.go",
} {
check(t, file)
}

View File

@ -0,0 +1,12 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
import "C"
type T = T // ERROR HERE
//export F
func F(p *T) {}

View File

@ -1418,9 +1418,18 @@ var goTypes = map[string]*Type{
// Map an ast type to a Type.
func (p *Package) cgoType(e ast.Expr) *Type {
return p.doCgoType(e, make(map[ast.Expr]bool))
}
// Map an ast type to a Type, avoiding cycles.
func (p *Package) doCgoType(e ast.Expr, m map[ast.Expr]bool) *Type {
if m[e] {
fatalf("%s: invalid recursive type", fset.Position(e.Pos()))
}
m[e] = true
switch t := e.(type) {
case *ast.StarExpr:
x := p.cgoType(t.X)
x := p.doCgoType(t.X, m)
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("%s*", x.C)}
case *ast.ArrayType:
if t.Len == nil {
@ -1465,7 +1474,12 @@ func (p *Package) cgoType(e ast.Expr) *Type {
continue
}
if ts.Name.Name == t.Name {
return p.cgoType(ts.Type)
// Give a better error than the one
// above if we detect a recursive type.
if m[ts.Type] {
fatalf("%s: invalid recursive type: %s refers to itself", fset.Position(e.Pos()), t.Name)
}
return p.doCgoType(ts.Type, m)
}
}
}