diff options
Diffstat (limited to '')
-rw-r--r-- | src/runtime/unsafe.go | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/runtime/unsafe.go b/src/runtime/unsafe.go new file mode 100644 index 0000000..54649e8 --- /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")) +} |