1// Copyright 2020 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 main
6
7import (
8	"runtime"
9	"time"
10	"unsafe"
11)
12
13func init() {
14	register("CheckPtrAlignmentNoPtr", CheckPtrAlignmentNoPtr)
15	register("CheckPtrAlignmentPtr", CheckPtrAlignmentPtr)
16	register("CheckPtrAlignmentNilPtr", CheckPtrAlignmentNilPtr)
17	register("CheckPtrArithmetic", CheckPtrArithmetic)
18	register("CheckPtrArithmetic2", CheckPtrArithmetic2)
19	register("CheckPtrSize", CheckPtrSize)
20	register("CheckPtrSmall", CheckPtrSmall)
21	register("CheckPtrSliceOK", CheckPtrSliceOK)
22	register("CheckPtrSliceFail", CheckPtrSliceFail)
23	register("CheckPtrAlignmentNested", CheckPtrAlignmentNested)
24}
25
26func CheckPtrAlignmentNoPtr() {
27	var x [2]int64
28	p := unsafe.Pointer(&x[0])
29	sink2 = (*int64)(unsafe.Pointer(uintptr(p) + 1))
30}
31
32func CheckPtrAlignmentPtr() {
33	var x [2]int64
34	p := unsafe.Pointer(&x[0])
35	sink2 = (**int64)(unsafe.Pointer(uintptr(p) + 1))
36}
37
38// CheckPtrAlignmentNilPtr tests that checkptrAlignment doesn't crash
39// on nil pointers (#47430).
40func CheckPtrAlignmentNilPtr() {
41	var do func(int)
42	do = func(n int) {
43		// Inflate the stack so runtime.shrinkstack gets called during GC
44		if n > 0 {
45			do(n - 1)
46		}
47
48		var p unsafe.Pointer
49		_ = (*int)(p)
50	}
51
52	go func() {
53		for {
54			runtime.GC()
55		}
56	}()
57
58	go func() {
59		for i := 0; ; i++ {
60			do(i % 1024)
61		}
62	}()
63
64	time.Sleep(time.Second)
65}
66
67func CheckPtrArithmetic() {
68	var x int
69	i := uintptr(unsafe.Pointer(&x))
70	sink2 = (*int)(unsafe.Pointer(i))
71}
72
73func CheckPtrArithmetic2() {
74	var x [2]int64
75	p := unsafe.Pointer(&x[1])
76	var one uintptr = 1
77	sink2 = unsafe.Pointer(uintptr(p) & ^one)
78}
79
80func CheckPtrSize() {
81	p := new(int64)
82	sink2 = p
83	sink2 = (*[100]int64)(unsafe.Pointer(p))
84}
85
86func CheckPtrSmall() {
87	sink2 = unsafe.Pointer(uintptr(1))
88}
89
90func CheckPtrSliceOK() {
91	p := new([4]int64)
92	sink2 = unsafe.Slice(&p[1], 3)
93}
94
95func CheckPtrSliceFail() {
96	p := new(int64)
97	sink2 = p
98	sink2 = unsafe.Slice(p, 100)
99}
100
101func CheckPtrAlignmentNested() {
102	s := make([]int8, 100)
103	p := unsafe.Pointer(&s[0])
104	n := 9
105	_ = ((*[10]int8)(unsafe.Pointer((*[10]int64)(unsafe.Pointer(&p)))))[:n:n]
106}
107