go: syscall: (*Proc).Call does not keep arguments live
The following test program should give the output of the ImageState
value for Windows, which for most systems is IMAGE_STATE_COMPLETE
. However, when trying to get the value into a slice it is possible for GC to mess up the slice and not get the updated value from the syscall.
Test program:
package main
import (
"fmt"
"runtime"
"syscall"
"unsafe"
)
var (
advapi32 = syscall.NewLazyDLL("advapi32.dll")
regGetValue = advapi32.NewProc("RegGetValueW")
)
const (
HKEY_LOCAL_MACHINE = 0x80000002
RRF_RT_REG_SZ = 0x00000002
)
func RegGetValue(hKey uintptr, lpSubKey *uint16, lpValue *uint16, dwFlags uint32, pdwType *uint32) (string, uint32, error) {
var buf [1024]uint16
bufSizeBytes := uint32(1024 * 2)
runtime.GC() // Everything works correctly if this line is removed
ret, _, callErr := regGetValue.Call(uintptr(hKey), uintptr(unsafe.Pointer(lpSubKey)), uintptr(unsafe.Pointer(lpValue)), uintptr(dwFlags), uintptr(unsafe.Pointer(pdwType)), uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&bufSizeBytes)))
if ret != 0 {
return "", bufSizeBytes, callErr
}
return syscall.UTF16ToString(buf[:]), bufSizeBytes, nil
}
func main() {
key, _ := syscall.UTF16PtrFromString("SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Setup\\\\State")
value, _ := syscall.UTF16PtrFromString("ImageState")
str, _, _ := RegGetValue(
HKEY_LOCAL_MACHINE,
key,
value,
RRF_RT_REG_SZ,
nil,
)
fmt.Printf("str: %s\n", str)
}
Expected response: str: IMAGE_STATE_COMPLETE
Actual response: str:
If the regGetValue.Call(...)
line is replace with syscall.Syscall9(regGetValue.Addr(), ...)
then the code works as intended.
Environment:
go version go1.6.2 windows/amd64
set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=
set GORACE=
set GOROOT=C:\go162
set GOTOOLDIR=C:\go162\pkg\tool\windows_amd64
set GO15VENDOREXPERIMENT=1
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 33 (26 by maintainers)
OS version: Windows 10 [10.0.10586]
The bug also happens in go1.7beta1