aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-02-14 07:42:40 -0800
committerAndrew Bonventre <andybons@golang.org>2018-04-30 16:55:49 +0000
commit50f65726a9ac8d6dd4bd2c1c609db16debd98d5c (patch)
treeec34beb0e5591a5f2f0984ed8ecfa2f9a839c359
parent93cfaa058a98efeead43f084589da8bb966ce3da (diff)
downloadgo-50f65726a9ac8d6dd4bd2c1c609db16debd98d5c.tar.gz
go-50f65726a9ac8d6dd4bd2c1c609db16debd98d5c.zip
[release-branch.go1.9] cmd/compile: permit go:cgo_import_dynamic anywhere
It's used on Solaris to import symbols from shared libraries, e.g., in golang.org/x/sys/unix and golang.org/x/net/internal/socket. We could use a different directive but that would require build tags in all the places that use it. Fixes golang/go#23939 Change-Id: I47fcf72a6d2862e304204705979c2056c2f78ec5 Reviewed-on: https://go-review.googlesource.com/94018 Run-TryBot: Andrew Bonventre <andybons@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> (cherry picked from commit 41d3d153eb76f000e9f6e9edf68ed441d15081cb) Reviewed-on: https://go-review.googlesource.com/110077 Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r--src/cmd/compile/internal/gc/noder.go28
-rw-r--r--src/cmd/go/internal/load/pkg.go1
2 files changed, 28 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index 7cd941206b..37fad2d714 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -1190,8 +1190,22 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
}
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
+ case strings.HasPrefix(text, "go:cgo_import_dynamic "):
+ // This is permitted for general use because Solaris
+ // code relies on it in golang.org/x/sys/unix and others.
+ fields := pragmaFields(text)
+ if len(fields) >= 4 {
+ lib := strings.Trim(fields[3], `"`)
+ if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
+ p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
+ }
+ p.pragcgobuf += p.pragcgo(pos, text)
+ return pragmaValue("go:cgo_import_dynamic")
+ }
+ fallthrough
case strings.HasPrefix(text, "go:cgo_"):
- // For security, we disallow //go:cgo_* directives outside cgo-generated files.
+ // For security, we disallow //go:cgo_* directives other
+ // than cgo_import_dynamic outside cgo-generated files.
// Exception: they are allowed in the standard library, for runtime and syscall.
if !isCgoGeneratedFile(pos) && !compiling_std {
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
@@ -1227,6 +1241,18 @@ func isCgoGeneratedFile(pos src.Pos) bool {
return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
}
+// safeArg reports whether arg is a "safe" command-line argument,
+// meaning that when it appears in a command-line, it probably
+// doesn't have some special meaning other than its own name.
+// This is copied from SafeArg in cmd/go/internal/load/pkg.go.
+func safeArg(name string) bool {
+ if name == "" {
+ return false
+ }
+ c := name[0]
+ return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
+}
+
func mkname(sym *types.Sym) *Node {
n := oldname(sym)
if n.Name != nil && n.Name.Pack != nil {
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 65b17012a3..6ca89d946d 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -1218,6 +1218,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
// GNU binutils flagfile specifiers, sometimes called "response files").
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
// We accept leading . _ and / as likely in file system paths.
+// There is a copy of this function in cmd/compile/internal/gc/noder.go.
func SafeArg(name string) bool {
if name == "" {
return false