aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorcuiweixie <cuiweixie@gmail.com>2022-08-16 17:52:13 +0800
committerMatthew Dempsky <mdempsky@google.com>2022-08-31 17:15:15 +0000
commitc7085329367e14f0aa828a3793cf66d9f82f05c2 (patch)
tree94f2e9ae0cfc74e1b3cd477480f718a2bd4b6814 /src/runtime
parent301ca7513f427f6511fb67cc0385151403cd1729 (diff)
downloadgo-c7085329367e14f0aa828a3793cf66d9f82f05c2.tar.xz
cmd/compile: add support for unsafe.{String,StringData,SliceData}
For #53003 Change-Id: I13a761daca8b433b271a1feb711c103d9820772d Reviewed-on: https://go-review.googlesource.com/c/go/+/423774 Reviewed-by: Heschi Kreinick <heschi@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: hopehook <hopehook@golangcn.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/checkptr_test.go2
-rw-r--r--src/runtime/slice.go48
-rw-r--r--src/runtime/testdata/testprog/checkptr.go13
-rw-r--r--src/runtime/unsafe.go98
4 files changed, 113 insertions, 48 deletions
diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go
index 15011ec494..811c0f0355 100644
--- a/src/runtime/checkptr_test.go
+++ b/src/runtime/checkptr_test.go
@@ -39,6 +39,8 @@ func TestCheckPtr(t *testing.T) {
{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
{"CheckPtrSliceOK", ""},
{"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"},
+ {"CheckPtrStringOK", ""},
+ {"CheckPtrStringFail", "fatal error: checkptr: unsafe.String result straddles multiple allocations\n"},
}
for _, tc := range testCases {
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index e537f15826..0a203e4101 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -123,54 +123,6 @@ func mulUintptr(a, b uintptr) (uintptr, bool) {
return math.MulUintptr(a, b)
}
-// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
-func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
- if len < 0 {
- panicunsafeslicelen()
- }
-
- if et.size == 0 {
- if ptr == nil && len > 0 {
- panicunsafeslicenilptr()
- }
- }
-
- mem, overflow := math.MulUintptr(et.size, uintptr(len))
- if overflow || mem > -uintptr(ptr) {
- if ptr == nil {
- panicunsafeslicenilptr()
- }
- panicunsafeslicelen()
- }
-}
-
-// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
-func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
- len := int(len64)
- if int64(len) != len64 {
- panicunsafeslicelen()
- }
- unsafeslice(et, ptr, len)
-}
-
-func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
- unsafeslice64(et, ptr, len64)
-
- // Check that underlying array doesn't straddle multiple heap objects.
- // unsafeslice64 has already checked for overflow.
- if checkptrStraddles(ptr, uintptr(len64)*et.size) {
- throw("checkptr: unsafe.Slice result straddles multiple allocations")
- }
-}
-
-func panicunsafeslicelen() {
- panic(errorString("unsafe.Slice: len out of range"))
-}
-
-func panicunsafeslicenilptr() {
- panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
-}
-
// growslice handles slice growth during append.
// It is passed the slice element type, the old slice, and the desired new minimum capacity,
// and it returns a new slice with at least that capacity, with the old data
diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go
index b27e5f74f8..60e71e66d7 100644
--- a/src/runtime/testdata/testprog/checkptr.go
+++ b/src/runtime/testdata/testprog/checkptr.go
@@ -20,6 +20,8 @@ func init() {
register("CheckPtrSmall", CheckPtrSmall)
register("CheckPtrSliceOK", CheckPtrSliceOK)
register("CheckPtrSliceFail", CheckPtrSliceFail)
+ register("CheckPtrStringOK", CheckPtrStringOK)
+ register("CheckPtrStringFail", CheckPtrStringFail)
register("CheckPtrAlignmentNested", CheckPtrAlignmentNested)
}
@@ -98,6 +100,17 @@ func CheckPtrSliceFail() {
sink2 = unsafe.Slice(p, 100)
}
+func CheckPtrStringOK() {
+ p := new([4]byte)
+ sink2 = unsafe.String(&p[1], 3)
+}
+
+func CheckPtrStringFail() {
+ p := new(byte)
+ sink2 = p
+ sink2 = unsafe.String(p, 100)
+}
+
func CheckPtrAlignmentNested() {
s := make([]int8, 100)
p := unsafe.Pointer(&s[0])
diff --git a/src/runtime/unsafe.go b/src/runtime/unsafe.go
new file mode 100644
index 0000000000..54649e8ff5
--- /dev/null
+++ b/src/runtime/unsafe.go
@@ -0,0 +1,98 @@
+// Copyright 2022 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 runtime
+
+import (
+ "runtime/internal/math"
+ "unsafe"
+)
+
+func unsafestring(ptr unsafe.Pointer, len int) {
+ if len < 0 {
+ panicunsafestringlen()
+ }
+
+ if uintptr(len) > -uintptr(ptr) {
+ if ptr == nil {
+ panicunsafestringnilptr()
+ }
+ panicunsafestringlen()
+ }
+}
+
+// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeString
+func unsafestring64(ptr unsafe.Pointer, len64 int64) {
+ len := int(len64)
+ if int64(len) != len64 {
+ panicunsafestringlen()
+ }
+ unsafestring(ptr, len)
+}
+
+func unsafestringcheckptr(ptr unsafe.Pointer, len64 int64) {
+ unsafestring64(ptr, len64)
+
+ // Check that underlying array doesn't straddle multiple heap objects.
+ // unsafestring64 has already checked for overflow.
+ if checkptrStraddles(ptr, uintptr(len64)) {
+ throw("checkptr: unsafe.String result straddles multiple allocations")
+ }
+}
+
+func panicunsafestringlen() {
+ panic(errorString("unsafe.String: len out of range"))
+}
+
+func panicunsafestringnilptr() {
+ panic(errorString("unsafe.String: ptr is nil and len is not zero"))
+}
+
+// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
+func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
+ if len < 0 {
+ panicunsafeslicelen()
+ }
+
+ if et.size == 0 {
+ if ptr == nil && len > 0 {
+ panicunsafeslicenilptr()
+ }
+ }
+
+ mem, overflow := math.MulUintptr(et.size, uintptr(len))
+ if overflow || mem > -uintptr(ptr) {
+ if ptr == nil {
+ panicunsafeslicenilptr()
+ }
+ panicunsafeslicelen()
+ }
+}
+
+// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice
+func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
+ len := int(len64)
+ if int64(len) != len64 {
+ panicunsafeslicelen()
+ }
+ unsafeslice(et, ptr, len)
+}
+
+func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
+ unsafeslice64(et, ptr, len64)
+
+ // Check that underlying array doesn't straddle multiple heap objects.
+ // unsafeslice64 has already checked for overflow.
+ if checkptrStraddles(ptr, uintptr(len64)*et.size) {
+ throw("checkptr: unsafe.Slice result straddles multiple allocations")
+ }
+}
+
+func panicunsafeslicelen() {
+ panic(errorString("unsafe.Slice: len out of range"))
+}
+
+func panicunsafeslicenilptr() {
+ panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
+}