github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/unsafe.go (about) 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 5 package runtime 6 7 import ( 8 "runtime/internal/math" 9 "unsafe" 10 ) 11 12 func 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 26 func unsafestring64(ptr unsafe.Pointer, len64 int64) { 27 len := int(len64) 28 if int64(len) != len64 { 29 panicunsafestringlen() 30 } 31 unsafestring(ptr, len) 32 } 33 34 func 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 44 func panicunsafestringlen() { 45 panic(errorString("unsafe.String: len out of range")) 46 } 47 48 func 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 53 func 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 74 func 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 82 func 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 92 func 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 99 func panicunsafeslicelen1(pc uintptr) { 100 panicCheck1(pc, "unsafe.Slice: len out of range") 101 panic(errorString("unsafe.Slice: len out of range")) 102 } 103 104 func 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 111 func 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 }