1// Copyright 2022 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package runtime 6 7import ( 8 "runtime/internal/math" 9 "unsafe" 10) 11 12func unsafestring(ptr unsafe.Pointer, len int) { 13 if len < 0 { 14 panicunsafestringlen() 15 } 16 17 if uintptr(len) > -uintptr(ptr) { 18 if ptr == nil { 19 panicunsafestringnilptr() 20 } 21 panicunsafestringlen() 22 } 23} 24 25// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeString 26func unsafestring64(ptr unsafe.Pointer, len64 int64) { 27 len := int(len64) 28 if int64(len) != len64 { 29 panicunsafestringlen() 30 } 31 unsafestring(ptr, len) 32} 33 34func unsafestringcheckptr(ptr unsafe.Pointer, len64 int64) { 35 unsafestring64(ptr, len64) 36 37 // Check that underlying array doesn't straddle multiple heap objects. 38 // unsafestring64 has already checked for overflow. 39 if checkptrStraddles(ptr, uintptr(len64)) { 40 throw("checkptr: unsafe.String result straddles multiple allocations") 41 } 42} 43 44func panicunsafestringlen() { 45 panic(errorString("unsafe.String: len out of range")) 46} 47 48func panicunsafestringnilptr() { 49 panic(errorString("unsafe.String: ptr is nil and len is not zero")) 50} 51 52// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice 53func unsafeslice(et *_type, ptr unsafe.Pointer, len int) { 54 if len < 0 { 55 panicunsafeslicelen1(getcallerpc()) 56 } 57 58 if et.Size_ == 0 { 59 if ptr == nil && len > 0 { 60 panicunsafeslicenilptr1(getcallerpc()) 61 } 62 } 63 64 mem, overflow := math.MulUintptr(et.Size_, uintptr(len)) 65 if overflow || mem > -uintptr(ptr) { 66 if ptr == nil { 67 panicunsafeslicenilptr1(getcallerpc()) 68 } 69 panicunsafeslicelen1(getcallerpc()) 70 } 71} 72 73// Keep this code in sync with cmd/compile/internal/walk/builtin.go:walkUnsafeSlice 74func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) { 75 len := int(len64) 76 if int64(len) != len64 { 77 panicunsafeslicelen1(getcallerpc()) 78 } 79 unsafeslice(et, ptr, len) 80} 81 82func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) { 83 unsafeslice64(et, ptr, len64) 84 85 // Check that underlying array doesn't straddle multiple heap objects. 86 // unsafeslice64 has already checked for overflow. 87 if checkptrStraddles(ptr, uintptr(len64)*et.Size_) { 88 throw("checkptr: unsafe.Slice result straddles multiple allocations") 89 } 90} 91 92func panicunsafeslicelen() { 93 // This is called only from compiler-generated code, so we can get the 94 // source of the panic. 95 panicunsafeslicelen1(getcallerpc()) 96} 97 98//go:yeswritebarrierrec 99func panicunsafeslicelen1(pc uintptr) { 100 panicCheck1(pc, "unsafe.Slice: len out of range") 101 panic(errorString("unsafe.Slice: len out of range")) 102} 103 104func panicunsafeslicenilptr() { 105 // This is called only from compiler-generated code, so we can get the 106 // source of the panic. 107 panicunsafeslicenilptr1(getcallerpc()) 108} 109 110//go:yeswritebarrierrec 111func panicunsafeslicenilptr1(pc uintptr) { 112 panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero") 113 panic(errorString("unsafe.Slice: ptr is nil and len is not zero")) 114} 115 116//go:linkname reflect_unsafeslice reflect.unsafeslice 117func reflect_unsafeslice(et *_type, ptr unsafe.Pointer, len int) { 118 unsafeslice(et, ptr, len) 119} 120