Skip to content

windows: fix -d=checkptr slice failures #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
11 changes: 2 additions & 9 deletions windows/env_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package windows

import (
"syscall"
"unicode/utf16"
"unsafe"
)

Expand Down Expand Up @@ -40,17 +39,11 @@ func (token Token) Environ(inheritExisting bool) (env []string, err error) {
defer DestroyEnvironmentBlock(block)
blockp := uintptr(unsafe.Pointer(block))
for {
entry := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(blockp))[:]
for i, v := range entry {
if v == 0 {
entry = entry[:i]
break
}
}
entry := UTF16PtrToString((*uint16)(unsafe.Pointer(blockp)))
if len(entry) == 0 {
break
}
env = append(env, string(utf16.Decode(entry)))
env = append(env, entry)
blockp += 2 * (uintptr(len(entry)) + 1)
}
return env, nil
Expand Down
20 changes: 15 additions & 5 deletions windows/security_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package windows
import (
"syscall"
"unsafe"

"golang.org/x/sys/internal/unsafeheader"
)

const (
Expand Down Expand Up @@ -1229,7 +1231,7 @@ func (sd *SECURITY_DESCRIPTOR) String() string {
return ""
}
defer LocalFree(Handle(unsafe.Pointer(sddl)))
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(sddl))[:])
return UTF16PtrToString(sddl)
}

// ToAbsolute converts a self-relative security descriptor into an absolute one.
Expand Down Expand Up @@ -1307,9 +1309,17 @@ func (absoluteSD *SECURITY_DESCRIPTOR) ToSelfRelative() (selfRelativeSD *SECURIT
}

func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor() *SECURITY_DESCRIPTOR {
sdBytes := make([]byte, selfRelativeSD.Length())
copy(sdBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(selfRelativeSD))[:len(sdBytes)])
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&sdBytes[0]))
sdLen := (int)(selfRelativeSD.Length())

var src []byte
h := (*unsafeheader.Slice)(unsafe.Pointer(&src))
h.Data = unsafe.Pointer(selfRelativeSD)
h.Len = sdLen
h.Cap = sdLen

dst := make([]byte, sdLen)
copy(dst, src)
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))
}

// SecurityDescriptorFromString converts an SDDL string describing a security descriptor into a
Expand Down Expand Up @@ -1391,6 +1401,6 @@ func ACLFromEntries(explicitEntries []EXPLICIT_ACCESS, mergedACL *ACL) (acl *ACL
}
defer LocalFree(Handle(unsafe.Pointer(winHeapACL)))
aclBytes := make([]byte, winHeapACL.aclSize)
copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes)])
copy(aclBytes, (*[(1 << 31) - 1]byte)(unsafe.Pointer(winHeapACL))[:len(aclBytes):len(aclBytes)])
return (*ACL)(unsafe.Pointer(&aclBytes[0])), nil
}
40 changes: 16 additions & 24 deletions windows/svc/mgr/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package mgr

import (
"syscall"
"unicode/utf16"
"unsafe"

"golang.org/x/sys/windows"
Expand Down Expand Up @@ -46,28 +45,21 @@ type Config struct {
DelayedAutoStart bool // the service is started after other auto-start services are started plus a short delay
}

func toString(p *uint16) string {
if p == nil {
return ""
}
return syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(p))[:])
}

func toStringSlice(ps *uint16) []string {
if ps == nil {
return nil
}
r := make([]string, 0)
for from, i, p := 0, 0, (*[1 << 24]uint16)(unsafe.Pointer(ps)); true; i++ {
if p[i] == 0 {
// empty string marks the end
if i <= from {
break
}
r = append(r, string(utf16.Decode(p[from:i])))
from = i + 1
p := unsafe.Pointer(ps)

for {
s := windows.UTF16PtrToString((*uint16)(p))
if len(s) == 0 {
break
}

r = append(r, s)
offset := unsafe.Sizeof(uint16(0)) * (uintptr)(len(s)+1)
p = unsafe.Pointer(uintptr(p) + offset)
}

return r
}

Expand Down Expand Up @@ -110,13 +102,13 @@ func (s *Service) Config() (Config, error) {
ServiceType: p.ServiceType,
StartType: p.StartType,
ErrorControl: p.ErrorControl,
BinaryPathName: toString(p.BinaryPathName),
LoadOrderGroup: toString(p.LoadOrderGroup),
BinaryPathName: windows.UTF16PtrToString(p.BinaryPathName),
LoadOrderGroup: windows.UTF16PtrToString(p.LoadOrderGroup),
TagId: p.TagId,
Dependencies: toStringSlice(p.Dependencies),
ServiceStartName: toString(p.ServiceStartName),
DisplayName: toString(p.DisplayName),
Description: toString(p2.Description),
ServiceStartName: windows.UTF16PtrToString(p.ServiceStartName),
DisplayName: windows.UTF16PtrToString(p.DisplayName),
Description: windows.UTF16PtrToString(p2.Description),
DelayedAutoStart: delayedStart,
}, nil
}
Expand Down
13 changes: 10 additions & 3 deletions windows/svc/mgr/mgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"unicode/utf16"
"unsafe"

"golang.org/x/sys/internal/unsafeheader"
"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -73,7 +74,7 @@ func (m *Mgr) LockStatus() (*LockStatus, error) {
status := &LockStatus{
IsLocked: lockStatus.IsLocked != 0,
Age: time.Duration(lockStatus.LockDuration) * time.Second,
Owner: windows.UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(lockStatus.LockOwner))[:]),
Owner: windows.UTF16PtrToString(lockStatus.LockOwner),
}
return status, nil
}
Expand Down Expand Up @@ -201,10 +202,16 @@ func (m *Mgr) ListServices() ([]string, error) {
if servicesReturned == 0 {
return nil, nil
}
services := (*[1 << 20]windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0]))[:servicesReturned]

var services []windows.ENUM_SERVICE_STATUS_PROCESS
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&services))
hdr.Data = unsafe.Pointer(&buf[0])
hdr.Len = int(servicesReturned)
hdr.Cap = int(servicesReturned)

var names []string
for _, s := range services {
name := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(s.ServiceName))[:])
name := windows.UTF16PtrToString(s.ServiceName)
names = append(names, name)
}
return names, nil
Expand Down
12 changes: 9 additions & 3 deletions windows/svc/mgr/recovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"
"unsafe"

"golang.org/x/sys/internal/unsafeheader"
"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -68,8 +69,13 @@ func (s *Service) RecoveryActions() ([]RecoveryAction, error) {
return nil, err
}

var actions []windows.SC_ACTION
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&actions))
hdr.Data = unsafe.Pointer(p.Actions)
hdr.Len = int(p.ActionsCount)
hdr.Cap = int(p.ActionsCount)

var recoveryActions []RecoveryAction
actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount]
for _, action := range actions {
recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
}
Expand Down Expand Up @@ -112,7 +118,7 @@ func (s *Service) RebootMessage() (string, error) {
return "", err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
return toString(p.RebootMsg), nil
return windows.UTF16PtrToString(p.RebootMsg), nil
}

// SetRecoveryCommand sets the command line of the process to execute in response to the RunCommand service controller action.
Expand All @@ -131,5 +137,5 @@ func (s *Service) RecoveryCommand() (string, error) {
return "", err
}
p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0]))
return toString(p.Command), nil
return windows.UTF16PtrToString(p.Command), nil
}
7 changes: 2 additions & 5 deletions windows/svc/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
package svc

import (
"unsafe"

"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -48,9 +46,8 @@ func IsAnInteractiveSession() (bool, error) {
if err != nil {
return false, err
}
p := unsafe.Pointer(&gs.Groups[0])
groups := (*[2 << 20]windows.SIDAndAttributes)(p)[:gs.GroupCount]
for _, g := range groups {

for _, g := range gs.AllGroups() {
if windows.EqualSid(g.Sid, interSid) {
return true, nil
}
Expand Down
11 changes: 9 additions & 2 deletions windows/svc/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"syscall"
"unsafe"

"golang.org/x/sys/internal/unsafeheader"
"golang.org/x/sys/windows"
)

Expand Down Expand Up @@ -224,10 +225,16 @@ const (
func (s *service) run() {
s.goWaits.Wait()
s.h = windows.Handle(ssHandle)
argv := (*[100]*int16)(unsafe.Pointer(sArgv))[:sArgc]

var argv []*uint16
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&argv))
hdr.Data = unsafe.Pointer(sArgv)
hdr.Len = int(sArgc)
hdr.Cap = int(sArgc)

args := make([]string, len(argv))
for i, a := range argv {
args[i] = syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(a))[:])
args[i] = windows.UTF16PtrToString(a)
}

cmdsToHandler := make(chan ChangeRequest)
Expand Down
30 changes: 29 additions & 1 deletion windows/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"time"
"unicode/utf16"
"unsafe"

"golang.org/x/sys/internal/unsafeheader"
)

type Handle uintptr
Expand Down Expand Up @@ -117,6 +119,32 @@ func UTF16PtrFromString(s string) (*uint16, error) {
return &a[0], nil
}

// UTF16PtrToString takes a pointer to a UTF-16 sequence and returns the corresponding UTF-8 encoded string.
// If the pointer is nil, this returns the empty string. This assumes that the UTF-16 sequence is terminated
// at a zero word; if the zero word is not present, the program may crash.
func UTF16PtrToString(p *uint16) string {
if p == nil {
return ""
}
if *p == 0 {
return ""
}

// Find NUL terminator.
n := 0
for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ {
ptr = unsafe.Pointer(uintptr(ptr) + unsafe.Sizeof(*p))
}

var s []uint16
h := (*unsafeheader.Slice)(unsafe.Pointer(&s))
h.Data = unsafe.Pointer(p)
h.Len = n
h.Cap = n

return string(utf16.Decode(s))
}

func Getpagesize() int { return 4096 }

// NewCallback converts a Go function to a function pointer conforming to the stdcall calling convention.
Expand Down Expand Up @@ -1383,7 +1411,7 @@ func (t Token) KnownFolderPath(folderID *KNOWNFOLDERID, flags uint32) (string, e
return "", err
}
defer CoTaskMemFree(unsafe.Pointer(p))
return UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:]), nil
return UTF16PtrToString(p), nil
}

// RtlGetVersion returns the version of the underlying operating system, ignoring
Expand Down