| // run | 
 |  | 
 | // Copyright 2018 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. | 
 |  | 
 | //go:build aix | 
 |  | 
 | package main | 
 |  | 
 | import "unsafe" | 
 |  | 
 | // Having a big address space means that indexing | 
 | // at a 1G + 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. | 
 | // The reason of the 1G offset is because AIX addresses start after 1G. | 
 | 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)) < 1<<32 { | 
 | 		panic("dummy not far enough") | 
 | 	} | 
 |  | 
 | 	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 << 33]byte = nil | 
 | 	println(p[1<<32+256<<20]) // very likely to be inside dummy, but should panic | 
 | } | 
 |  | 
 | var xb byte | 
 |  | 
 | func p2() { | 
 | 	var p *[1 << 33]byte = nil | 
 | 	xb = 123 | 
 |  | 
 | 	// Array index. | 
 | 	println(p[uintptr(unsafe.Pointer(&xb))]) // should panic | 
 | } | 
 |  | 
 | func p3() { | 
 | 	// Array to slice. | 
 | 	var p *[1 << 33]byte = nil | 
 | 	var x []byte = p[0:] // should panic | 
 | 	_ = x | 
 | } | 
 |  | 
 | var q *[1 << 33]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 << 33]byte = nil | 
 | 	fb(p[0:]) // should crash | 
 | } | 
 |  | 
 | func p6() { | 
 | 	// Array to slice. | 
 | 	var p *[1 << 33]byte = nil | 
 | 	var _ []byte = p[10 : len(p)-10] // should crash | 
 | } | 
 |  | 
 | type T struct { | 
 | 	x [1<<32 + 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 | 
 | 	} | 
 | } |