1
0
mirror of https://github.com/golang/go synced 2024-11-19 20:54:39 -07:00

misc/cgo/test: get uintptr, not pointer, from dlopen

The dlopen function returns an opaque handle, and it is possible for
it to look like a Go pointer, causing garbage collector and cgo
confusion.

Fixes #23663

Change-Id: Id080e2bbcee8cfa7ac4a457a927f96949eb913f8
Reviewed-on: https://go-review.googlesource.com/91596
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Ian Lance Taylor 2018-02-02 05:38:08 -08:00
parent 851e98f0ee
commit 2a8229d96e
2 changed files with 30 additions and 6 deletions

View File

@ -4,6 +4,25 @@
// +build !windows // +build !windows
#include <stdint.h>
#include <dlfcn.h>
// Write our own versions of dlopen/dlsym/dlclose so that we represent
// the opaque handle as a Go uintptr rather than a Go pointer to avoid
// garbage collector confusion. See issue 23663.
uintptr_t dlopen4029(char* name, int flags) {
return (uintptr_t)(dlopen(name, flags));
}
uintptr_t dlsym4029(uintptr_t handle, char* name) {
return (uintptr_t)(dlsym((void*)(handle), name));
}
int dlclose4029(uintptr_t handle) {
return dlclose((void*)(handle));
}
void call4029(void *arg) { void call4029(void *arg) {
void (*fn)(void) = arg; void (*fn)(void) = arg;
fn(); fn();

View File

@ -7,10 +7,15 @@
package cgotest package cgotest
/* /*
#include <stdint.h>
#include <dlfcn.h> #include <dlfcn.h>
#cgo linux LDFLAGS: -ldl #cgo linux LDFLAGS: -ldl
extern void call4029(void *arg); extern uintptr_t dlopen4029(char*, int);
extern uintptr_t dlsym4029(uintptr_t, char*);
extern int dlclose4029(uintptr_t);
extern void call4029(uintptr_t arg);
*/ */
import "C" import "C"
@ -51,15 +56,15 @@ func test4029(t *testing.T) {
} }
func loadThySelf(t *testing.T, symbol string) { func loadThySelf(t *testing.T, symbol string) {
this_process := C.dlopen(nil, C.RTLD_NOW) this_process := C.dlopen4029(nil, C.RTLD_NOW)
if this_process == nil { if this_process == 0 {
t.Error("dlopen:", C.GoString(C.dlerror())) t.Error("dlopen:", C.GoString(C.dlerror()))
return return
} }
defer C.dlclose(this_process) defer C.dlclose4029(this_process)
symbol_address := C.dlsym(this_process, C.CString(symbol)) symbol_address := C.dlsym4029(this_process, C.CString(symbol))
if symbol_address == nil { if symbol_address == 0 {
t.Error("dlsym:", C.GoString(C.dlerror())) t.Error("dlsym:", C.GoString(C.dlerror()))
return return
} }