1// run
2
3// Copyright 2011 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// Test that the implementation catches nil ptr indirection
8// in a large address space.
9
10// Address space starts at 1<<32 on AIX and on darwin/arm64 and on windows/arm64, so dummy is too far.
11//go:build !aix && (!darwin || !arm64) && (!windows || !arm64)
12
13package main
14
15import "unsafe"
16
17// Having a big address space means that indexing
18// at a 256 MB offset from a nil pointer might not
19// cause a memory access fault. This test checks
20// that Go is doing the correct explicit checks to catch
21// these nil pointer accesses, not just relying on the hardware.
22var dummy [256 << 20]byte // give us a big address space
23
24func main() {
25	// the test only tests what we intend to test
26	// if dummy starts in the first 256 MB of memory.
27	// otherwise there might not be anything mapped
28	// at the address that might be accidentally
29	// dereferenced below.
30	if uintptr(unsafe.Pointer(&dummy)) > 256<<20 {
31		panic("dummy too far out")
32	}
33
34	shouldPanic(p1)
35	shouldPanic(p2)
36	shouldPanic(p3)
37	shouldPanic(p4)
38	shouldPanic(p5)
39	shouldPanic(p6)
40	shouldPanic(p7)
41	shouldPanic(p8)
42	shouldPanic(p9)
43	shouldPanic(p10)
44	shouldPanic(p11)
45	shouldPanic(p12)
46	shouldPanic(p13)
47	shouldPanic(p14)
48	shouldPanic(p15)
49	shouldPanic(p16)
50}
51
52func shouldPanic(f func()) {
53	defer func() {
54		if recover() == nil {
55			panic("memory reference did not panic")
56		}
57	}()
58	f()
59}
60
61func p1() {
62	// Array index.
63	var p *[1 << 30]byte = nil
64	println(p[256<<20]) // very likely to be inside dummy, but should panic
65}
66
67var xb byte
68
69func p2() {
70	var p *[1 << 30]byte = nil
71	xb = 123
72
73	// Array index.
74	println(p[uintptr(unsafe.Pointer(&xb))]) // should panic
75}
76
77func p3() {
78	// Array to slice.
79	var p *[1 << 30]byte = nil
80	var x []byte = p[0:] // should panic
81	_ = x
82}
83
84var q *[1 << 30]byte
85
86func p4() {
87	// Array to slice.
88	var x []byte
89	var y = &x
90	*y = q[0:] // should crash (uses arraytoslice runtime routine)
91}
92
93func fb([]byte) {
94	panic("unreachable")
95}
96
97func p5() {
98	// Array to slice.
99	var p *[1 << 30]byte = nil
100	fb(p[0:]) // should crash
101}
102
103func p6() {
104	// Array to slice.
105	var p *[1 << 30]byte = nil
106	var _ []byte = p[10 : len(p)-10] // should crash
107}
108
109type T struct {
110	x [256 << 20]byte
111	i int
112}
113
114func f() *T {
115	return nil
116}
117
118var y *T
119var x = &y
120
121func p7() {
122	// Struct field access with large offset.
123	println(f().i) // should crash
124}
125
126func p8() {
127	// Struct field access with large offset.
128	println((*x).i) // should crash
129}
130
131func p9() {
132	// Struct field access with large offset.
133	var t *T
134	println(&t.i) // should crash
135}
136
137func p10() {
138	// Struct field access with large offset.
139	var t *T
140	println(t.i) // should crash
141}
142
143type T1 struct {
144	T
145}
146
147type T2 struct {
148	*T1
149}
150
151func p11() {
152	t := &T2{}
153	p := &t.i
154	println(*p)
155}
156
157// ADDR(DOT(IND(p))) needs a check also
158func p12() {
159	var p *T = nil
160	println(*(&((*p).i)))
161}
162
163// Tests suggested in golang.org/issue/6080.
164
165func p13() {
166	var x *[10]int
167	y := x[:]
168	_ = y
169}
170
171func p14() {
172	println((*[1]int)(nil)[:])
173}
174
175func p15() {
176	for i := range (*[1]int)(nil)[:] {
177		_ = i
178	}
179}
180
181func p16() {
182	for i, v := range (*[1]int)(nil)[:] {
183		_ = i + v
184	}
185}
186