|  | // run | 
|  |  | 
|  | // 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. | 
|  |  | 
|  | // Test that the implementation catches nil ptr indirection | 
|  | // in a large address space. | 
|  |  | 
|  | // +build !aix | 
|  | // +build !darwin !arm64 | 
|  | // +build !windows !arm64 | 
|  | // Address space starts at 1<<32 on AIX and on darwin/arm64 and on windows/arm64, so dummy is too far. | 
|  |  | 
|  | 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) | 
|  | shouldPanic(p11) | 
|  | shouldPanic(p12) | 
|  | shouldPanic(p13) | 
|  | shouldPanic(p14) | 
|  | shouldPanic(p15) | 
|  | shouldPanic(p16) | 
|  | } | 
|  |  | 
|  | 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 | 
|  | } | 
|  |  | 
|  | type T1 struct { | 
|  | T | 
|  | } | 
|  |  | 
|  | type T2 struct { | 
|  | *T1 | 
|  | } | 
|  |  | 
|  | func p11() { | 
|  | t := &T2{} | 
|  | p := &t.i | 
|  | println(*p) | 
|  | } | 
|  |  | 
|  | // ADDR(DOT(IND(p))) needs a check also | 
|  | func p12() { | 
|  | var p *T = nil | 
|  | println(*(&((*p).i))) | 
|  | } | 
|  |  | 
|  | // Tests suggested in golang.org/issue/6080. | 
|  |  | 
|  | func p13() { | 
|  | var x *[10]int | 
|  | y := x[:] | 
|  | _ = y | 
|  | } | 
|  |  | 
|  | func p14() { | 
|  | println((*[1]int)(nil)[:]) | 
|  | } | 
|  |  | 
|  | func p15() { | 
|  | for i := range (*[1]int)(nil)[:] { | 
|  | _ = i | 
|  | } | 
|  | } | 
|  |  | 
|  | func p16() { | 
|  | for i, v := range (*[1]int)(nil)[:] { | 
|  | _ = i + v | 
|  | } | 
|  | } |