mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: run cgo pointer checks for pointer to union
If a C union type (or a C++ class type) can contain a pointer field, then run the cgo checks on pointers to that type. This will test the pointer as though it were an unsafe.Pointer, and will crash if it points to Go memory that contains a pointer. Fixes #15942. Change-Id: Ic2d07ed9648d4b27078ae7683e26196bcbc59fc9 Reviewed-on: https://go-review.googlesource.com/33237 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
fab3fcaf75
commit
27b68474ca
2 changed files with 77 additions and 0 deletions
|
|
@ -802,6 +802,11 @@ func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
|
|||
if !top {
|
||||
return true
|
||||
}
|
||||
// Check whether this is a pointer to a C union (or class)
|
||||
// type that contains a pointer.
|
||||
if unionWithPointer[t.X] {
|
||||
return true
|
||||
}
|
||||
return p.hasPointer(f, t.X, false)
|
||||
case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
|
||||
return true
|
||||
|
|
@ -1418,6 +1423,10 @@ var tagGen int
|
|||
var typedef = make(map[string]*Type)
|
||||
var goIdent = make(map[string]*ast.Ident)
|
||||
|
||||
// unionWithPointer is true for a Go type that represents a C union (or class)
|
||||
// that may contain a pointer. This is used for cgo pointer checking
|
||||
var unionWithPointer = make(map[ast.Expr]bool)
|
||||
|
||||
func (c *typeConv) Init(ptrSize, intSize int64) {
|
||||
c.ptrSize = ptrSize
|
||||
c.intSize = intSize
|
||||
|
|
@ -1706,6 +1715,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
t.Size = t1.Size
|
||||
t.Align = t1.Align
|
||||
t.Go = t1.Go
|
||||
if unionWithPointer[t1.Go] {
|
||||
unionWithPointer[t.Go] = true
|
||||
}
|
||||
t.EnumValues = nil
|
||||
t.Typedef = ""
|
||||
t.C.Set("%s "+dt.Qual, t1.C)
|
||||
|
|
@ -1740,6 +1752,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
switch dt.Kind {
|
||||
case "class", "union":
|
||||
t.Go = c.Opaque(t.Size)
|
||||
if c.dwarfHasPointer(dt, pos) {
|
||||
unionWithPointer[t.Go] = true
|
||||
}
|
||||
if t.C.Empty() {
|
||||
t.C.Set("__typeof__(unsigned char[%d])", t.Size)
|
||||
}
|
||||
|
|
@ -1782,6 +1797,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
goIdent[name.Name] = name
|
||||
sub := c.Type(dt.Type, pos)
|
||||
t.Go = name
|
||||
if unionWithPointer[sub.Go] {
|
||||
unionWithPointer[t.Go] = true
|
||||
}
|
||||
t.Size = sub.Size
|
||||
t.Align = sub.Align
|
||||
oldType := typedef[name.Name]
|
||||
|
|
@ -2163,6 +2181,44 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
|||
return
|
||||
}
|
||||
|
||||
// dwarfHasPointer returns whether the DWARF type dt contains a pointer.
|
||||
func (c *typeConv) dwarfHasPointer(dt dwarf.Type, pos token.Pos) bool {
|
||||
switch dt := dt.(type) {
|
||||
default:
|
||||
fatalf("%s: unexpected type: %s", lineno(pos), dt)
|
||||
return false
|
||||
|
||||
case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.EnumType,
|
||||
*dwarf.FloatType, *dwarf.ComplexType, *dwarf.FuncType,
|
||||
*dwarf.IntType, *dwarf.UcharType, *dwarf.UintType, *dwarf.VoidType:
|
||||
|
||||
return false
|
||||
|
||||
case *dwarf.ArrayType:
|
||||
return c.dwarfHasPointer(dt.Type, pos)
|
||||
|
||||
case *dwarf.PtrType:
|
||||
return true
|
||||
|
||||
case *dwarf.QualType:
|
||||
return c.dwarfHasPointer(dt.Type, pos)
|
||||
|
||||
case *dwarf.StructType:
|
||||
for _, f := range dt.Field {
|
||||
if c.dwarfHasPointer(f.Type, pos) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
case *dwarf.TypedefType:
|
||||
if dt.Name == "_GoString_" || dt.Name == "_GoBytes_" {
|
||||
return true
|
||||
}
|
||||
return c.dwarfHasPointer(dt.Type, pos)
|
||||
}
|
||||
}
|
||||
|
||||
func upper(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue