summaryrefslogtreecommitdiffstats
path: root/misc/cgo/testsanitizers/testdata/msan6.go
diff options
context:
space:
mode:
Diffstat (limited to 'misc/cgo/testsanitizers/testdata/msan6.go')
-rw-r--r--misc/cgo/testsanitizers/testdata/msan6.go72
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)
+}