]> Cypherpunks.ru repositories - gostls13.git/blob - misc/cgo/testsanitizers/testdata/msan6.go
e96e8f9ead57f73a0e593324a1dba7d2f84ed624
[gostls13.git] / misc / cgo / testsanitizers / testdata / msan6.go
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package main
6
7 // A C function returning a value on the Go stack could leave the Go
8 // stack marked as uninitialized, potentially causing a later error
9 // when the stack is used for something else. Issue 26209.
10
11 /*
12 #cgo LDFLAGS: -fsanitize=memory
13 #cgo CPPFLAGS: -fsanitize=memory
14
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 typedef struct {
20         uintptr_t a[20];
21 } S;
22
23 S f() {
24         S *p;
25
26         p = (S *)(malloc(sizeof(S)));
27         p->a[0] = 0;
28         return *p;
29 }
30 */
31 import "C"
32
33 // allocateStack extends the stack so that stack copying doesn't
34 // confuse the msan data structures.
35 //
36 //go:noinline
37 func allocateStack(i int) int {
38         if i == 0 {
39                 return i
40         }
41         return allocateStack(i - 1)
42 }
43
44 // F1 marks a chunk of stack as uninitialized.
45 // C.f returns an uninitialized struct on the stack, so msan will mark
46 // the stack as uninitialized.
47 //
48 //go:noinline
49 func F1() uintptr {
50         s := C.f()
51         return uintptr(s.a[0])
52 }
53
54 // F2 allocates a struct on the stack and converts it to an empty interface,
55 // which will call msanread and see that the data appears uninitialized.
56 //
57 //go:noinline
58 func F2() interface{} {
59         return C.S{}
60 }
61
62 func poisonStack(i int) int {
63         if i == 0 {
64                 return int(F1())
65         }
66         F1()
67         r := poisonStack(i - 1)
68         F2()
69         return r
70 }
71
72 func main() {
73         allocateStack(16384)
74         poisonStack(128)
75 }