// 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 { panicunsafeslicelen1(getcallerpc()) } if et.Size_ == 0 { if ptr == nil && len > 0 { panicunsafeslicenilptr1(getcallerpc()) } } mem, overflow := math.MulUintptr(et.Size_, uintptr(len)) if overflow || mem > -uintptr(ptr) { if ptr == nil { panicunsafeslicenilptr1(getcallerpc()) } panicunsafeslicelen1(getcallerpc()) } } // 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 { panicunsafeslicelen1(getcallerpc()) } 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() { // This is called only from compiler-generated code, so we can get the // source of the panic. panicunsafeslicelen1(getcallerpc()) } //go:yeswritebarrierrec func panicunsafeslicelen1(pc uintptr) { panicCheck1(pc, "unsafe.Slice: len out of range") panic(errorString("unsafe.Slice: len out of range")) } func panicunsafeslicenilptr() { // This is called only from compiler-generated code, so we can get the // source of the panic. panicunsafeslicenilptr1(getcallerpc()) } //go:yeswritebarrierrec func panicunsafeslicenilptr1(pc uintptr) { panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero") panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) } //go:linkname reflect_unsafeslice reflect.unsafeslice func reflect_unsafeslice(et *_type, ptr unsafe.Pointer, len int) { unsafeslice(et, ptr, len) }