]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
setupapi: safer aliasing of slice types
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 3 May 2019 07:34:00 +0000 (09:34 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Fri, 3 May 2019 07:34:00 +0000 (09:34 +0200)
tun/wintun/guid/guid_windows.go
tun/wintun/guid/zguid_windows.go
tun/wintun/setupapi/setupapi_windows.go
tun/wintun/setupapi/setupapi_windows_test.go
tun/wintun/wintun_windows.go

index 0078d2c09bef35cbdbc1ee53d57da7b0e33a26e8..c5f4be6a9db3a9fd5589ac6d54ef812451c94858 100644 (file)
@@ -12,7 +12,7 @@ import (
        "golang.org/x/sys/windows"
 )
 
-//sys  clsidFromString(lpsz *uint16, pclsid *windows.GUID) (hr int32) = ole32.CLSIDFromString
+//sys  clsidFromString(lpsz *uint16, pclsid *windows.GUID) (err error) [failretval!=0] = ole32.CLSIDFromString
 
 //
 // FromString parses "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" string to GUID.
@@ -22,14 +22,11 @@ func FromString(str string) (*windows.GUID, error) {
        if err != nil {
                return nil, err
        }
-
        guid := &windows.GUID{}
-
-       hr := clsidFromString(strUTF16, guid)
-       if hr < 0 {
-               return nil, syscall.Errno(hr)
+       err = clsidFromString(strUTF16, guid)
+       if err != nil {
+               return nil, err
        }
-
        return guid, nil
 }
 
index 5467849ff0946cdf649defde633454a19231803e..b0b4cce360ac113f52ebf1e44ce759f32802cb42 100644 (file)
@@ -42,8 +42,14 @@ var (
        procCLSIDFromString = modole32.NewProc("CLSIDFromString")
 )
 
-func clsidFromString(lpsz *uint16, pclsid *windows.GUID) (hr int32) {
-       r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0)
-       hr = int32(r0)
+func clsidFromString(lpsz *uint16, pclsid *windows.GUID) (err error) {
+       r1, _, e1 := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0)
+       if r1 != 0 {
+               if e1 != 0 {
+                       err = errnoErr(e1)
+               } else {
+                       err = syscall.EINVAL
+               }
+       }
        return
 }
index dec9da20fa87669c4963f1314b821c57e64c8fea..621d12b2c75455ae6d0a0b9b0d27da6749d6c024 100644 (file)
@@ -8,6 +8,7 @@ package setupapi
 import (
        "encoding/binary"
        "fmt"
+       "runtime"
        "syscall"
        "unsafe"
 
@@ -261,9 +262,13 @@ func SetupDiGetDeviceRegistryProperty(deviceInfoSet DevInfo, deviceInfoData *Dev
 func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
        switch dataType {
        case windows.REG_SZ:
-               return windows.UTF16ToString(BufToUTF16(buf)), nil
+               ret := windows.UTF16ToString(bufToUTF16(buf))
+               runtime.KeepAlive(buf)
+               return ret, nil
        case windows.REG_EXPAND_SZ:
-               return registry.ExpandString(windows.UTF16ToString(BufToUTF16(buf)))
+               ret, err := registry.ExpandString(windows.UTF16ToString(bufToUTF16(buf)))
+               runtime.KeepAlive(buf)
+               return ret, err
        case windows.REG_BINARY:
                return buf, nil
        case windows.REG_DWORD_LITTLE_ENDIAN:
@@ -271,7 +276,7 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
        case windows.REG_DWORD_BIG_ENDIAN:
                return binary.BigEndian.Uint32(buf), nil
        case windows.REG_MULTI_SZ:
-               bufW := BufToUTF16(buf)
+               bufW := bufToUTF16(buf)
                a := []string{}
                for i := 0; i < len(bufW); {
                        j := i + wcslen(bufW[i:])
@@ -280,6 +285,7 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
                        }
                        i = j + 1
                }
+               runtime.KeepAlive(buf)
                return a, nil
        case windows.REG_QWORD_LITTLE_ENDIAN:
                return binary.LittleEndian.Uint64(buf), nil
@@ -288,8 +294,8 @@ func getRegistryValue(buf []byte, dataType uint32) (interface{}, error) {
        }
 }
 
-// BufToUTF16 function reinterprets []byte buffer as []uint16
-func BufToUTF16(buf []byte) []uint16 {
+// bufToUTF16 function reinterprets []byte buffer as []uint16
+func bufToUTF16(buf []byte) []uint16 {
        sl := struct {
                addr *uint16
                len  int
@@ -298,8 +304,8 @@ func BufToUTF16(buf []byte) []uint16 {
        return *(*[]uint16)(unsafe.Pointer(&sl))
 }
 
-// UTF16ToBuf function reinterprets []uint16 as []byte
-func UTF16ToBuf(buf []uint16) []byte {
+// utf16ToBuf function reinterprets []uint16 as []byte
+func utf16ToBuf(buf []uint16) []byte {
        sl := struct {
                addr *byte
                len  int
@@ -334,6 +340,16 @@ func (deviceInfoSet DevInfo) SetDeviceRegistryProperty(deviceInfoData *DevInfoDa
        return SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, propertyBuffers)
 }
 
+func (deviceInfoSet DevInfo) SetDeviceRegistryPropertyString(deviceInfoData *DevInfoData, property SPDRP, str string) error {
+       str16, err := windows.UTF16FromString(str)
+       if err != nil {
+               return err
+       }
+       err = SetupDiSetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, utf16ToBuf(append(str16, 0)))
+       runtime.KeepAlive(str16)
+       return err
+}
+
 //sys  setupDiGetDeviceInstallParams(deviceInfoSet DevInfo, deviceInfoData *DevInfoData, deviceInstallParams *DevInstallParams) (err error) = setupapi.SetupDiGetDeviceInstallParamsW
 
 // SetupDiGetDeviceInstallParams function retrieves device installation parameters for a device information set or a particular device information element.
index 73cad7cd79d77fcef41dd816b8e0fcd4e52fff3a..d5443ff98be5729ad059b6208906720681784668 100644 (file)
@@ -6,6 +6,7 @@
 package setupapi
 
 import (
+       "runtime"
        "strings"
        "syscall"
        "testing"
@@ -471,7 +472,7 @@ func TestSetupDiGetSelectedDevice(t *testing.T) {
 
 func TestUTF16ToBuf(t *testing.T) {
        buf := []uint16{0x0123, 0x4567, 0x89ab, 0xcdef}
-       buf2 := UTF16ToBuf(buf)
+       buf2 := utf16ToBuf(buf)
        if len(buf)*2 != len(buf2) ||
                cap(buf)*2 != cap(buf2) ||
                buf2[0] != 0x23 || buf2[1] != 0x01 ||
@@ -480,4 +481,5 @@ func TestUTF16ToBuf(t *testing.T) {
                buf2[6] != 0xef || buf2[7] != 0xcd {
                t.Errorf("SetupDiSetSelectedDevice(nil) should fail with ERROR_INVALID_USER_BUFFER")
        }
+       runtime.KeepAlive(buf)
 }
index e1b46a838aee11ce7bd25577eabde3a003d3f4fe..69f6eb61ffdb735d1596dc2aae1db44731122c71 100644 (file)
@@ -218,11 +218,7 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err
        }
 
        // Set Plug&Play device hardware ID property.
-       hwid, err := syscall.UTF16FromString(hardwareID)
-       if err != nil {
-               return nil, false, err // syscall.UTF16FromString(hardwareID) should never fail: hardwareID is const string without NUL chars.
-       }
-       err = devInfoList.SetDeviceRegistryProperty(deviceData, setupapi.SPDRP_HARDWAREID, setupapi.UTF16ToBuf(append(hwid, 0)))
+       err = devInfoList.SetDeviceRegistryPropertyString(deviceData, setupapi.SPDRP_HARDWAREID, hardwareID)
        if err != nil {
                return nil, false, errors.New("SetupDiSetDeviceRegistryProperty(SPDRP_HARDWAREID) failed: " + err.Error())
        }