diff options
Diffstat (limited to 'test/nilptr.go')
| -rw-r--r-- | test/nilptr.go | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/test/nilptr.go b/test/nilptr.go new file mode 100644 index 000000000..b0c1df2d9 --- /dev/null +++ b/test/nilptr.go @@ -0,0 +1,129 @@ +// $G $D/$F.go && $L $F.$A && ./$A.out + +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "unsafe" + +// Having a big address space means that indexing +// at a 256 MB offset from a nil pointer might not +// cause a memory access fault. This test checks +// that Go is doing the correct explicit checks to catch +// these nil pointer accesses, not just relying on the hardware. +var dummy [256 << 20]byte // give us a big address space + +func main() { + // the test only tests what we intend to test + // if dummy starts in the first 256 MB of memory. + // otherwise there might not be anything mapped + // at the address that might be accidentally + // dereferenced below. + if uintptr(unsafe.Pointer(&dummy)) > 256<<20 { + panic("dummy too far out") + } + + shouldPanic(p1) + shouldPanic(p2) + shouldPanic(p3) + shouldPanic(p4) + shouldPanic(p5) + shouldPanic(p6) + shouldPanic(p7) + shouldPanic(p8) + shouldPanic(p9) + shouldPanic(p10) +} + +func shouldPanic(f func()) { + defer func() { + if recover() == nil { + panic("memory reference did not panic") + } + }() + f() +} + +func p1() { + // Array index. + var p *[1 << 30]byte = nil + println(p[256<<20]) // very likely to be inside dummy, but should panic +} + +var xb byte + +func p2() { + var p *[1 << 30]byte = nil + xb = 123 + + // Array index. + println(p[uintptr(unsafe.Pointer(&xb))]) // should panic +} + +func p3() { + // Array to slice. + var p *[1 << 30]byte = nil + var x []byte = p[0:] // should panic + _ = x +} + +var q *[1 << 30]byte + +func p4() { + // Array to slice. + var x []byte + var y = &x + *y = q[0:] // should crash (uses arraytoslice runtime routine) +} + +func fb([]byte) { + panic("unreachable") +} + +func p5() { + // Array to slice. + var p *[1 << 30]byte = nil + fb(p[0:]) // should crash +} + +func p6() { + // Array to slice. + var p *[1 << 30]byte = nil + var _ []byte = p[10 : len(p)-10] // should crash +} + +type T struct { + x [256 << 20]byte + i int +} + +func f() *T { + return nil +} + +var y *T +var x = &y + +func p7() { + // Struct field access with large offset. + println(f().i) // should crash +} + +func p8() { + // Struct field access with large offset. + println((*x).i) // should crash +} + +func p9() { + // Struct field access with large offset. + var t *T + println(&t.i) // should crash +} + +func p10() { + // Struct field access with large offset. + var t *T + println(t.i) // should crash +} |
