diff options
author | Clément Chigot <clement.chigot@atos.net> | 2018-10-16 15:59:43 +0200 |
---|---|---|
committer | Lynn Boger <laboger@linux.vnet.ibm.com> | 2018-11-26 14:13:53 +0000 |
commit | 9fe9853ae5641eda4cfa58015bd0bcedb99c12cb (patch) | |
tree | 7d9f5dc6ec5ab99abe48eb30c009291dabe02e5b /test/nilptr_aix.go | |
parent | 041526c6ef669743afc6c4b757b95011f1475d1a (diff) | |
download | go-git-9fe9853ae5641eda4cfa58015bd0bcedb99c12cb.tar.gz |
cmd/compile: fix nilcheck for AIX
This commit adapts compile tool to create correct nilchecks for AIX.
AIX allows to load a nil pointer. Therefore, the default nilcheck
which issues a load must be replaced by a CMP instruction followed by a
store at 0x0 if the value is nil. The store will trigger a SIGSEGV as on
others OS.
The nilcheck algorithm must be adapted to do not remove nilcheck if it's
only a read. Stores are detected with v.Type.IsMemory().
Tests related to nilptr must be adapted to the previous changements.
nilptr.go cannot be used as it's because the AIX address space starts at
1<<32.
Change-Id: I9f5aaf0b7e185d736a9b119c0ed2fe4e5bd1e7af
Reviewed-on: https://go-review.googlesource.com/c/144538
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'test/nilptr_aix.go')
-rw-r--r-- | test/nilptr_aix.go | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/test/nilptr_aix.go b/test/nilptr_aix.go new file mode 100644 index 0000000000..ea5fcc3f4e --- /dev/null +++ b/test/nilptr_aix.go @@ -0,0 +1,185 @@ +// 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. + +// +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 + } +} |