1// Copyright 2013 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// This file contains tests for the copylock checker's 6// function declaration analysis. 7 8package a 9 10import "sync" 11 12func OkFunc(*sync.Mutex) {} 13func BadFunc(sync.Mutex) {} // want "BadFunc passes lock by value: sync.Mutex" 14func BadFunc2(sync.Map) {} // want "BadFunc2 passes lock by value: sync.Map contains sync.Mutex" 15func OkRet() *sync.Mutex {} 16func BadRet() sync.Mutex {} // Don't warn about results 17 18var ( 19 OkClosure = func(*sync.Mutex) {} 20 BadClosure = func(sync.Mutex) {} // want "func passes lock by value: sync.Mutex" 21 BadClosure2 = func(sync.Map) {} // want "func passes lock by value: sync.Map contains sync.Mutex" 22) 23 24type EmbeddedRWMutex struct { 25 sync.RWMutex 26} 27 28func (*EmbeddedRWMutex) OkMeth() {} 29func (EmbeddedRWMutex) BadMeth() {} // want "BadMeth passes lock by value: a.EmbeddedRWMutex" 30func OkFunc(e *EmbeddedRWMutex) {} 31func BadFunc(EmbeddedRWMutex) {} // want "BadFunc passes lock by value: a.EmbeddedRWMutex" 32func OkRet() *EmbeddedRWMutex {} 33func BadRet() EmbeddedRWMutex {} // Don't warn about results 34 35type FieldMutex struct { 36 s sync.Mutex 37} 38 39func (*FieldMutex) OkMeth() {} 40func (FieldMutex) BadMeth() {} // want "BadMeth passes lock by value: a.FieldMutex contains sync.Mutex" 41func OkFunc(*FieldMutex) {} 42func BadFunc(FieldMutex, int) {} // want "BadFunc passes lock by value: a.FieldMutex contains sync.Mutex" 43 44type L0 struct { 45 L1 46} 47 48type L1 struct { 49 l L2 50} 51 52type L2 struct { 53 sync.Mutex 54} 55 56func (*L0) Ok() {} 57func (L0) Bad() {} // want "Bad passes lock by value: a.L0 contains a.L1 contains a.L2" 58 59type EmbeddedMutexPointer struct { 60 s *sync.Mutex // safe to copy this pointer 61} 62 63func (*EmbeddedMutexPointer) Ok() {} 64func (EmbeddedMutexPointer) AlsoOk() {} 65func StillOk(EmbeddedMutexPointer) {} 66func LookinGood() EmbeddedMutexPointer {} 67 68type EmbeddedLocker struct { 69 sync.Locker // safe to copy interface values 70} 71 72func (*EmbeddedLocker) Ok() {} 73func (EmbeddedLocker) AlsoOk() {} 74 75type CustomLock struct{} 76 77func (*CustomLock) Lock() {} 78func (*CustomLock) Unlock() {} 79 80func Ok(*CustomLock) {} 81func Bad(CustomLock) {} // want "Bad passes lock by value: a.CustomLock" 82 83// Passing lock values into interface function arguments 84func FuncCallInterfaceArg(f func(a int, b interface{})) { 85 var m sync.Mutex 86 var t struct{ lock sync.Mutex } 87 88 f(1, "foo") 89 f(2, &t) 90 f(3, &sync.Mutex{}) 91 f(4, m) // want "call of f copies lock value: sync.Mutex" 92 f(5, t) // want "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 93 var fntab []func(t) 94 fntab[0](t) // want "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 95} 96 97// Returning lock via interface value 98func ReturnViaInterface(x int) (int, interface{}) { 99 var m sync.Mutex 100 var t struct{ lock sync.Mutex } 101 102 switch x % 4 { 103 case 0: 104 return 0, "qwe" 105 case 1: 106 return 1, &sync.Mutex{} 107 case 2: 108 return 2, m // want "return copies lock value: sync.Mutex" 109 default: 110 return 3, t // want "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 111 } 112} 113 114// Some cases that we don't warn about. 115 116func AcceptedCases() { 117 x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227) 118 x = BadRet() // function call on RHS is OK (#16227) 119 x = *OKRet() // indirection of function call on RHS is OK (#16227) 120} 121 122// TODO: Unfortunate cases 123 124// Non-ideal error message: 125// Since we're looking for Lock methods, sync.Once's underlying 126// sync.Mutex gets called out, but without any reference to the sync.Once. 127type LocalOnce sync.Once 128 129func (LocalOnce) Bad() {} // want "Bad passes lock by value: a.LocalOnce contains sync.Mutex" 130 131// False negative: 132// LocalMutex doesn't have a Lock method. 133// Nevertheless, it is probably a bad idea to pass it by value. 134type LocalMutex sync.Mutex 135 136func (LocalMutex) Bad() {} // WANTED: An error here :( 137