123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- // 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)
- }
|