// Copyright 2020 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 // This is for issue #63739. // Ensure that parameters are kept alive until the end of the C call. If not, // then a stack copy at just the right time while calling into C might think // that any stack pointers are not alive and fail to update them, causing the C // function to see the old, no longer correct, pointer values. /* int add_from_multiple_pointers(int *a, int *b, int *c) { *a = *a + 1; *b = *b + 1; *c = *c + 1; return *a + *b + *c; } #cgo noescape add_from_multiple_pointers #cgo nocallback add_from_multiple_pointers */ import "C" import ( "fmt" ) const ( maxStack = 1024 ) func init() { register("CgoEscapeWithMultiplePointers", CgoEscapeWithMultiplePointers) } func CgoEscapeWithMultiplePointers() { stackGrow(maxStack) fmt.Println("OK") } //go:noinline func testCWithMultiplePointers() { var a C.int = 1 var b C.int = 2 var c C.int = 3 v := C.add_from_multiple_pointers(&a, &b, &c) if v != 9 || a != 2 || b != 3 || c != 4 { fmt.Printf("%d + %d + %d != %d\n", a, b, c, v) } } func stackGrow(n int) { if n == 0 { return } testCWithMultiplePointers() stackGrow(n - 1) }