Source file src/runtime/unsafe.go

     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  }
   115  
   116  //go:linkname reflect_unsafeslice reflect.unsafeslice
   117  func reflect_unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
   118  	unsafeslice(et, ptr, len)
   119  }
   120  

View as plain text