diff options
Diffstat (limited to 'misc/cgo/testsanitizers/testdata/msan6.go')
-rw-r--r-- | misc/cgo/testsanitizers/testdata/msan6.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/misc/cgo/testsanitizers/testdata/msan6.go b/misc/cgo/testsanitizers/testdata/msan6.go new file mode 100644 index 0000000..003989c --- /dev/null +++ b/misc/cgo/testsanitizers/testdata/msan6.go @@ -0,0 +1,72 @@ +// 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. + +package main + +// A C function returning a value on the Go stack could leave the Go +// stack marked as uninitialized, potentially causing a later error +// when the stack is used for something else. Issue 26209. + +/* +#cgo LDFLAGS: -fsanitize=memory +#cgo CPPFLAGS: -fsanitize=memory + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +typedef struct { + uintptr_t a[20]; +} S; + +S f() { + S *p; + + p = (S *)(malloc(sizeof(S))); + p->a[0] = 0; + return *p; +} +*/ +import "C" + +// allocateStack extends the stack so that stack copying doesn't +// confuse the msan data structures. +//go:noinline +func allocateStack(i int) int { + if i == 0 { + return i + } + return allocateStack(i - 1) +} + +// F1 marks a chunk of stack as uninitialized. +// C.f returns an uninitialized struct on the stack, so msan will mark +// the stack as uninitialized. +//go:noinline +func F1() uintptr { + s := C.f() + return uintptr(s.a[0]) +} + +// F2 allocates a struct on the stack and converts it to an empty interface, +// which will call msanread and see that the data appears uninitialized. +//go:noinline +func F2() interface{} { + return C.S{} +} + +func poisonStack(i int) int { + if i == 0 { + return int(F1()) + } + F1() + r := poisonStack(i - 1) + F2() + return r +} + +func main() { + allocateStack(16384) + poisonStack(128) +} |