From: Hiroshi Ioka Date: Tue, 4 Dec 2018 23:01:07 +0000 (+0900) Subject: cmd/cgo: reject names that are likely to be mangled C name X-Git-Tag: go1.12beta1~166 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5e1727892bf36076ee45c417b56bba32801ffbd7;p=gostls13.git cmd/cgo: reject names that are likely to be mangled C name Fixes #28721 Change-Id: I00356f3a9b0c2fb21dc9c2237dd5296fcb3b319b Reviewed-on: https://go-review.googlesource.com/c/152657 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go index 0d7ca4cf9d..d2a72a46f4 100644 --- a/misc/cgo/errors/errors_test.go +++ b/misc/cgo/errors/errors_test.go @@ -121,6 +121,7 @@ func TestReportsTypeErrors(t *testing.T) { "issue16591.go", "issue18452.go", "issue18889.go", + "issue28721.go", } { check(t, file) } diff --git a/misc/cgo/errors/src/issue28721.go b/misc/cgo/errors/src/issue28721.go new file mode 100644 index 0000000000..0eb2a9271c --- /dev/null +++ b/misc/cgo/errors/src/issue28721.go @@ -0,0 +1,29 @@ +// Copyright 2018 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. + +// cgo should reject the use of mangled C names. + +package main + +/* +typedef struct a { + int i; +} a; +void fn(void) {} +*/ +import "C" + +type B _Ctype_struct_a // ERROR HERE + +var a _Ctype_struct_a // ERROR HERE + +type A struct { + a *_Ctype_struct_a // ERROR HERE +} + +var notExist _Ctype_NotExist // ERROR HERE + +func main() { + _Cfunc_fn() // ERROR HERE +} diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 06058cb570..83d727a8a5 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -145,6 +145,7 @@ func (f *File) ParseGo(name string, src []byte) { if f.Ref == nil { f.Ref = make([]*Ref, 0, 8) } + f.walk(ast2, ctxProg, (*File).validateIdents) f.walk(ast2, ctxProg, (*File).saveExprs) // Accumulate exported functions. @@ -181,6 +182,14 @@ func commentText(g *ast.CommentGroup) string { return strings.Join(pieces, "") } +func (f *File) validateIdents(x interface{}, context astContext) { + if x, ok := x.(*ast.Ident); ok { + if f.isMangledName(x.Name) { + error_(x.Pos(), "identifier %q may conflict with identifiers generated by cgo", x.Name) + } + } +} + // Save various references we are going to need later. func (f *File) saveExprs(x interface{}, context astContext) { switch x := x.(type) { diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 4464b840dd..b59bfe68fe 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -719,6 +719,19 @@ func (p *Package) mangleName(n *Name) { n.Mangle = prefix + n.Kind + "_" + n.Go } +func (f *File) isMangledName(s string) bool { + prefix := "_C" + if strings.HasPrefix(s, prefix) { + t := s[len(prefix):] + for _, k := range nameKinds { + if strings.HasPrefix(t, k+"_") { + return true + } + } + } + return false +} + // rewriteCalls rewrites all calls that pass pointers to check that // they follow the rules for passing pointers between Go and C. // This reports whether the package needs to import unsafe as _cgo_unsafe. diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 7a845b17a4..80435b0634 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -106,13 +106,15 @@ func (r *Ref) Pos() token.Pos { return (*r.Expr).Pos() } +var nameKinds = []string{"iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type"} + // A Name collects information about C.xxx. type Name struct { Go string // name used in Go referring to package C Mangle string // name used in generated Go C string // name used in C Define string // #define expansion - Kind string // "iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type" + Kind string // one of the nameKinds Type *Type // the type of xxx FuncType *FuncType AddError bool