mirror of
https://github.com/golang/sys.git
synced 2026-02-09 04:06:04 +03:00
windows,windows\svc,windows\svc\mgr: use unsafe.Slice instead of unsafeheader.Slice
unsafe.Slice is available since Go 1.17, which is already the minimum version supported by this package. This change removes the dependency on the internal unsafeheader package, which can be removed from the module. Change-Id: I6c34cb152f2336ea04c5f9c7e88797ed8914f9cc Reviewed-on: https://go-review.googlesource.com/c/sys/+/526635 Run-TryBot: Quim Muntal <quimmuntal@gmail.com> Reviewed-by: Bryan Mills <bcmills@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
// Copyright 2020 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 unsafeheader contains header declarations for the Go runtime's
|
||||
// slice and string implementations.
|
||||
//
|
||||
// This package allows x/sys to use types equivalent to
|
||||
// reflect.SliceHeader and reflect.StringHeader without introducing
|
||||
// a dependency on the (relatively heavy) "reflect" package.
|
||||
package unsafeheader
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Slice is the runtime representation of a slice.
|
||||
// It cannot be used safely or portably and its representation may change in a later release.
|
||||
type Slice struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
Cap int
|
||||
}
|
||||
|
||||
// String is the runtime representation of a string.
|
||||
// It cannot be used safely or portably and its representation may change in a later release.
|
||||
type String struct {
|
||||
Data unsafe.Pointer
|
||||
Len int
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright 2020 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 unsafeheader_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
// TestTypeMatchesReflectType ensures that the name and layout of the
|
||||
// unsafeheader types matches the corresponding Header types in the reflect
|
||||
// package.
|
||||
func TestTypeMatchesReflectType(t *testing.T) {
|
||||
t.Run("Slice", func(t *testing.T) {
|
||||
testHeaderMatchesReflect(t, unsafeheader.Slice{}, reflect.SliceHeader{})
|
||||
})
|
||||
|
||||
t.Run("String", func(t *testing.T) {
|
||||
testHeaderMatchesReflect(t, unsafeheader.String{}, reflect.StringHeader{})
|
||||
})
|
||||
}
|
||||
|
||||
func testHeaderMatchesReflect(t *testing.T, header, reflectHeader interface{}) {
|
||||
h := reflect.TypeOf(header)
|
||||
rh := reflect.TypeOf(reflectHeader)
|
||||
|
||||
for i := 0; i < h.NumField(); i++ {
|
||||
f := h.Field(i)
|
||||
rf, ok := rh.FieldByName(f.Name)
|
||||
if !ok {
|
||||
t.Errorf("Field %d of %v is named %s, but no such field exists in %v", i, h, f.Name, rh)
|
||||
continue
|
||||
}
|
||||
if !typeCompatible(f.Type, rf.Type) {
|
||||
t.Errorf("%v.%s has type %v, but %v.%s has type %v", h, f.Name, f.Type, rh, rf.Name, rf.Type)
|
||||
}
|
||||
if f.Offset != rf.Offset {
|
||||
t.Errorf("%v.%s has offset %d, but %v.%s has offset %d", h, f.Name, f.Offset, rh, rf.Name, rf.Offset)
|
||||
}
|
||||
}
|
||||
|
||||
if h.NumField() != rh.NumField() {
|
||||
t.Errorf("%v has %d fields, but %v has %d", h, h.NumField(), rh, rh.NumField())
|
||||
}
|
||||
if h.Align() != rh.Align() {
|
||||
t.Errorf("%v has alignment %d, but %v has alignment %d", h, h.Align(), rh, rh.Align())
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
unsafePointerType = reflect.TypeOf(unsafe.Pointer(nil))
|
||||
uintptrType = reflect.TypeOf(uintptr(0))
|
||||
)
|
||||
|
||||
func typeCompatible(t, rt reflect.Type) bool {
|
||||
return t == rt || (t == unsafePointerType && rt == uintptrType)
|
||||
}
|
||||
|
||||
// TestWriteThroughHeader ensures that the headers in the unsafeheader package
|
||||
// can successfully mutate variables of the corresponding built-in types.
|
||||
//
|
||||
// This test is expected to fail under -race (which implicitly enables
|
||||
// -d=checkptr) if the runtime views the header types as incompatible with the
|
||||
// underlying built-in types.
|
||||
func TestWriteThroughHeader(t *testing.T) {
|
||||
t.Run("Slice", func(t *testing.T) {
|
||||
s := []byte("Hello, checkptr!")[:5]
|
||||
|
||||
var alias []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&alias))
|
||||
hdr.Data = unsafe.Pointer(&s[0])
|
||||
hdr.Cap = cap(s)
|
||||
hdr.Len = len(s)
|
||||
|
||||
if !bytes.Equal(alias, s) {
|
||||
t.Errorf("alias of %T(%q) constructed via Slice = %T(%q)", s, s, alias, alias)
|
||||
}
|
||||
if cap(alias) != cap(s) {
|
||||
t.Errorf("alias of %T with cap %d has cap %d", s, cap(s), cap(alias))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("String", func(t *testing.T) {
|
||||
s := "Hello, checkptr!"
|
||||
|
||||
var alias string
|
||||
hdr := (*unsafeheader.String)(unsafe.Pointer(&alias))
|
||||
hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data
|
||||
hdr.Len = len(s)
|
||||
|
||||
if alias != s {
|
||||
t.Errorf("alias of %q constructed via String = %q", s, alias)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -7,8 +7,6 @@ package windows
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -1341,21 +1339,14 @@ func (selfRelativeSD *SECURITY_DESCRIPTOR) copySelfRelativeSecurityDescriptor()
|
||||
sdLen = min
|
||||
}
|
||||
|
||||
var src []byte
|
||||
h := (*unsafeheader.Slice)(unsafe.Pointer(&src))
|
||||
h.Data = unsafe.Pointer(selfRelativeSD)
|
||||
h.Len = sdLen
|
||||
h.Cap = sdLen
|
||||
|
||||
src := unsafe.Slice((*byte)(unsafe.Pointer(selfRelativeSD)), sdLen)
|
||||
// SECURITY_DESCRIPTOR has pointers in it, which means checkptr expects for it to
|
||||
// be aligned properly. When we're copying a Windows-allocated struct to a
|
||||
// Go-allocated one, make sure that the Go allocation is aligned to the
|
||||
// pointer size.
|
||||
const psize = int(unsafe.Sizeof(uintptr(0)))
|
||||
|
||||
var dst []byte
|
||||
h = (*unsafeheader.Slice)(unsafe.Pointer(&dst))
|
||||
alloc := make([]uintptr, (sdLen+psize-1)/psize)
|
||||
h.Data = (*unsafeheader.Slice)(unsafe.Pointer(&alloc)).Data
|
||||
h.Len = sdLen
|
||||
h.Cap = sdLen
|
||||
|
||||
dst := unsafe.Slice((*byte)(unsafe.Pointer(&alloc[0])), sdLen)
|
||||
copy(dst, src)
|
||||
return (*SECURITY_DESCRIPTOR)(unsafe.Pointer(&dst[0]))
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -199,12 +198,7 @@ func (m *Mgr) ListServices() ([]string, error) {
|
||||
if servicesReturned == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
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)
|
||||
services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0])), int(servicesReturned))
|
||||
|
||||
var names []string
|
||||
for _, s := range services {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -70,12 +69,7 @@ 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)
|
||||
|
||||
actions := unsafe.Slice(p.Actions, int(p.ActionsCount))
|
||||
var recoveryActions []RecoveryAction
|
||||
for _, action := range actions {
|
||||
recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond})
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -222,11 +221,7 @@ func serviceMain(argc uint32, argv **uint16) uintptr {
|
||||
defer func() {
|
||||
theService.h = 0
|
||||
}()
|
||||
var args16 []*uint16
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&args16))
|
||||
hdr.Data = unsafe.Pointer(argv)
|
||||
hdr.Len = int(argc)
|
||||
hdr.Cap = int(argc)
|
||||
args16 := unsafe.Slice(argv, int(argc))
|
||||
|
||||
args := make([]string, len(args16))
|
||||
for i, a := range args16 {
|
||||
|
||||
@@ -15,8 +15,6 @@ import (
|
||||
"time"
|
||||
"unicode/utf16"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
type Handle uintptr
|
||||
@@ -1667,12 +1665,8 @@ func NewNTUnicodeString(s string) (*NTUnicodeString, error) {
|
||||
|
||||
// Slice returns a uint16 slice that aliases the data in the NTUnicodeString.
|
||||
func (s *NTUnicodeString) Slice() []uint16 {
|
||||
var slice []uint16
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&slice))
|
||||
hdr.Data = unsafe.Pointer(s.Buffer)
|
||||
hdr.Len = int(s.Length)
|
||||
hdr.Cap = int(s.MaximumLength)
|
||||
return slice
|
||||
slice := unsafe.Slice(s.Buffer, s.MaximumLength)
|
||||
return slice[:s.Length]
|
||||
}
|
||||
|
||||
func (s *NTUnicodeString) String() string {
|
||||
@@ -1695,12 +1689,8 @@ func NewNTString(s string) (*NTString, error) {
|
||||
|
||||
// Slice returns a byte slice that aliases the data in the NTString.
|
||||
func (s *NTString) Slice() []byte {
|
||||
var slice []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&slice))
|
||||
hdr.Data = unsafe.Pointer(s.Buffer)
|
||||
hdr.Len = int(s.Length)
|
||||
hdr.Cap = int(s.MaximumLength)
|
||||
return slice
|
||||
slice := unsafe.Slice(s.Buffer, s.MaximumLength)
|
||||
return slice[:s.Length]
|
||||
}
|
||||
|
||||
func (s *NTString) String() string {
|
||||
@@ -1752,10 +1742,7 @@ func LoadResourceData(module, resInfo Handle) (data []byte, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
h := (*unsafeheader.Slice)(unsafe.Pointer(&data))
|
||||
h.Data = unsafe.Pointer(ptr)
|
||||
h.Len = int(size)
|
||||
h.Cap = int(size)
|
||||
data = unsafe.Slice((*byte)(unsafe.Pointer(ptr)), size)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
@@ -865,10 +864,7 @@ func TestSystemModuleVersions(t *testing.T) {
|
||||
return
|
||||
}
|
||||
mods := (*windows.RTL_PROCESS_MODULES)(unsafe.Pointer(&moduleBuffer[0]))
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&modules))
|
||||
hdr.Data = unsafe.Pointer(&mods.Modules[0])
|
||||
hdr.Len = int(mods.NumberOfModules)
|
||||
hdr.Cap = int(mods.NumberOfModules)
|
||||
modules = unsafe.Slice(&mods.Modules[0], int(mods.NumberOfModules))
|
||||
break
|
||||
}
|
||||
for i := range modules {
|
||||
|
||||
Reference in New Issue
Block a user