Source file test/unsafebuiltins.go

     1  // run
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package main
     8  
     9  import (
    10  	"math"
    11  	"unsafe"
    12  )
    13  
    14  const maxUintptr = 1 << (8 * unsafe.Sizeof(uintptr(0)))
    15  
    16  func main() {
    17  	var p [10]byte
    18  
    19  	// unsafe.Add
    20  	{
    21  		p1 := unsafe.Pointer(&p[1])
    22  		assert(unsafe.Add(p1, 1) == unsafe.Pointer(&p[2]))
    23  		assert(unsafe.Add(p1, -1) == unsafe.Pointer(&p[0]))
    24  	}
    25  
    26  	// unsafe.Slice
    27  	{
    28  		s := unsafe.Slice(&p[0], len(p))
    29  		assert(&s[0] == &p[0])
    30  		assert(len(s) == len(p))
    31  		assert(cap(s) == len(p))
    32  
    33  		// nil pointer with zero length returns nil
    34  		assert(unsafe.Slice((*int)(nil), 0) == nil)
    35  
    36  		// nil pointer with positive length panics
    37  		mustPanic(func() { _ = unsafe.Slice((*int)(nil), 1) })
    38  
    39  		// negative length
    40  		var neg int = -1
    41  		mustPanic(func() { _ = unsafe.Slice(new(byte), neg) })
    42  
    43  		// length too large
    44  		var tooBig uint64 = math.MaxUint64
    45  		mustPanic(func() { _ = unsafe.Slice(new(byte), tooBig) })
    46  
    47  		// size overflows address space
    48  		mustPanic(func() { _ = unsafe.Slice(new(uint64), maxUintptr/8) })
    49  		mustPanic(func() { _ = unsafe.Slice(new(uint64), maxUintptr/8+1) })
    50  
    51  		// sliced memory overflows address space
    52  		last := (*byte)(unsafe.Pointer(^uintptr(0)))
    53  		_ = unsafe.Slice(last, 1)
    54  		mustPanic(func() { _ = unsafe.Slice(last, 2) })
    55  	}
    56  
    57  	// unsafe.String
    58  	{
    59  		s := unsafe.String(&p[0], len(p))
    60  		assert(s == string(p[:]))
    61  		assert(len(s) == len(p))
    62  
    63  		// the empty string
    64  		assert(unsafe.String(nil, 0) == "")
    65  
    66  		// nil pointer with positive length panics
    67  		mustPanic(func() { _ = unsafe.String(nil, 1) })
    68  
    69  		// negative length
    70  		var neg int = -1
    71  		mustPanic(func() { _ = unsafe.String(new(byte), neg) })
    72  
    73  		// length too large
    74  		var tooBig uint64 = math.MaxUint64
    75  		mustPanic(func() { _ = unsafe.String(new(byte), tooBig) })
    76  
    77  		// string memory overflows address space
    78  		last := (*byte)(unsafe.Pointer(^uintptr(0)))
    79  		_ = unsafe.String(last, 1)
    80  		mustPanic(func() { _ = unsafe.String(last, 2) })
    81  	}
    82  
    83  	// unsafe.StringData
    84  	{
    85  		var s = "string"
    86  		assert(string(unsafe.Slice(unsafe.StringData(s), len(s))) == s)
    87  	}
    88  
    89  	//unsafe.SliceData
    90  	{
    91  		var s = []byte("slice")
    92  		assert(unsafe.String(unsafe.SliceData(s), len(s)) == string(s))
    93  	}
    94  }
    95  
    96  func assert(ok bool) {
    97  	if !ok {
    98  		panic("FAIL")
    99  	}
   100  }
   101  
   102  func mustPanic(f func()) {
   103  	defer func() {
   104  		assert(recover() != nil)
   105  	}()
   106  	f()
   107  }
   108  

View as plain text