1 // Copyright 2016 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 gc 6 7 import "testing" 8 9 type T struct { 10 x [2]int64 // field that will be clobbered. Also makes type not SSAable. 11 p *byte // has a pointer 12 } 13 14 //go:noinline 15 func makeT() T { 16 return T{} 17 } 18 19 var g T 20 21 var sink interface{} 22 23 func TestIssue15854(t *testing.T) { 24 for i := 0; i < 10000; i++ { 25 if g.x[0] != 0 { 26 t.Fatalf("g.x[0] clobbered with %x\n", g.x[0]) 27 } 28 // The bug was in the following assignment. The return 29 // value of makeT() is not copied out of the args area of 30 // stack frame in a timely fashion. So when write barriers 31 // are enabled, the marshaling of the args for the write 32 // barrier call clobbers the result of makeT() before it is 33 // read by the write barrier code. 34 g = makeT() 35 sink = make([]byte, 1000) // force write barriers to eventually happen 36 } 37 } 38 func TestIssue15854b(t *testing.T) { 39 const N = 10000 40 a := make([]T, N) 41 for i := 0; i < N; i++ { 42 a = append(a, makeT()) 43 sink = make([]byte, 1000) // force write barriers to eventually happen 44 } 45 for i, v := range a { 46 if v.x[0] != 0 { 47 t.Fatalf("a[%d].x[0] clobbered with %x\n", i, v.x[0]) 48 } 49 } 50 } 51