]> Cypherpunks repositories - gostls13.git/commitdiff
plugin: resolve plugin import path issue
authorTodd Neal <todd@tneal.org>
Tue, 25 Apr 2017 23:32:48 +0000 (19:32 -0400)
committerTodd Neal <todd@tneal.org>
Wed, 26 Apr 2017 00:54:54 +0000 (00:54 +0000)
Resolve import paths to get plugin symbol prefixes.

Fixes #19534

Change-Id: Ic25d83e72465ba8f6be0337218a1627b5dc702dc
Reviewed-on: https://go-review.googlesource.com/40994
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
misc/cgo/testplugin/src/issue19534/main.go [new file with mode: 0644]
misc/cgo/testplugin/src/issue19534/plugin.go [new file with mode: 0644]
misc/cgo/testplugin/test.bash
src/plugin/plugin_dlopen.go

diff --git a/misc/cgo/testplugin/src/issue19534/main.go b/misc/cgo/testplugin/src/issue19534/main.go
new file mode 100644 (file)
index 0000000..de263b6
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 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 main
+
+import "plugin"
+
+func main() {
+       p, err := plugin.Open("plugin.so")
+       if err != nil {
+               panic(err)
+       }
+
+       sym, err := p.Lookup("Foo")
+       if err != nil {
+               panic(err)
+       }
+       f := sym.(func() int)
+       if f() != 42 {
+               panic("expected f() == 42")
+       }
+}
diff --git a/misc/cgo/testplugin/src/issue19534/plugin.go b/misc/cgo/testplugin/src/issue19534/plugin.go
new file mode 100644 (file)
index 0000000..582d333
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2017 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 main
+
+func Foo() int {
+       return 42
+}
index ab7430acc37f95e580492a1aa341c51e5eaa41e6..69df5bd2bfaca9fd350720b219eb84e08b8440f5 100755 (executable)
@@ -16,7 +16,7 @@ goarch=$(go env GOARCH)
 
 function cleanup() {
        rm -f plugin*.so unnamed*.so iface*.so
-       rm -rf host pkg sub iface issue18676
+       rm -rf host pkg sub iface issue18676 issue19534
 }
 trap cleanup EXIT
 
@@ -44,3 +44,9 @@ LD_LIBRARY_PATH=$(pwd) ./iface
 GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
 GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
 timeout 10s ./issue18676
+
+# Test for issue 19534 - that we can load a plugin built in a path with non-alpha
+# characters
+GOPATH=$(pwd) go build -buildmode=plugin -ldflags='-pluginpath=issue.19534' -o plugin.so src/issue19534/plugin.go
+GOPATH=$(pwd) go build -o issue19534 src/issue19534/main.go
+./issue19534
index 72e219e337ce3664203f5479f9b4ea9ac8330233..3237598f06b22748e55b53714fc1940da149dfc5 100644 (file)
@@ -39,6 +39,47 @@ import (
        "unsafe"
 )
 
+// avoid a dependency on strings
+func lastIndexByte(s string, c byte) int {
+       for i := len(s) - 1; i >= 0; i-- {
+               if s[i] == c {
+                       return i
+               }
+       }
+       return -1
+}
+
+// pathToPrefix converts raw string to the prefix that will be used in the symbol
+// table. If modifying, modify the version in internal/obj/sym.go as well.
+func pathToPrefix(s string) string {
+       slash := lastIndexByte(s, '/')
+       // check for chars that need escaping
+       n := 0
+       for r := 0; r < len(s); r++ {
+               if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+                       n++
+               }
+       }
+
+       // quick exit
+       if n == 0 {
+               return s
+       }
+
+       // escape
+       const hex = "0123456789abcdef"
+       p := make([]byte, 0, len(s)+2*n)
+       for r := 0; r < len(s); r++ {
+               if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
+                       p = append(p, '%', hex[c>>4], hex[c&0xF])
+               } else {
+                       p = append(p, c)
+               }
+       }
+
+       return string(p)
+}
+
 func open(name string) (*Plugin, error) {
        cPath := (*C.char)(C.malloc(C.PATH_MAX + 1))
        defer C.free(unsafe.Pointer(cPath))
@@ -103,7 +144,7 @@ func open(name string) (*Plugin, error) {
                        delete(syms, symName)
                        symName = symName[1:]
                }
-               cname := C.CString(pluginpath + "." + symName)
+               cname := C.CString(pathToPrefix(pluginpath) + "." + symName)
                p := C.pluginLookup(h, cname, &cErr)
                C.free(unsafe.Pointer(cname))
                if p == nil {