]> Cypherpunks.ru repositories - gostls13.git/blob - misc/cgo/testsanitizers/testdata/msan6.go
003989c2beaba2511a0677f870468b237bb9e522
[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 //go:noinline
36 func allocateStack(i int) int {
37         if i == 0 {
38                 return i
39         }
40         return allocateStack(i - 1)
41 }
42
43 // F1 marks a chunk of stack as uninitialized.
44 // C.f returns an uninitialized struct on the stack, so msan will mark
45 // the stack as uninitialized.
46 //go:noinline
47 func F1() uintptr {
48         s := C.f()
49         return uintptr(s.a[0])
50 }
51
52 // F2 allocates a struct on the stack and converts it to an empty interface,
53 // which will call msanread and see that the data appears uninitialized.
54 //go:noinline
55 func F2() interface{} {
56         return C.S{}
57 }
58
59 func poisonStack(i int) int {
60         if i == 0 {
61                 return int(F1())
62         }
63         F1()
64         r := poisonStack(i - 1)
65         F2()
66         return r
67 }
68
69 func main() {
70         allocateStack(16384)
71         poisonStack(128)
72 }