1// Package staticcheck contains a linter for Go source code.
2package staticcheck // import "honnef.co/go/tools/staticcheck"
3
4import (
5	"fmt"
6	"go/ast"
7	"go/constant"
8	"go/token"
9	"go/types"
10	htmltemplate "html/template"
11	"net/http"
12	"reflect"
13	"regexp"
14	"regexp/syntax"
15	"sort"
16	"strconv"
17	"strings"
18	texttemplate "text/template"
19	"unicode"
20
21	. "honnef.co/go/tools/arg"
22	"honnef.co/go/tools/code"
23	"honnef.co/go/tools/deprecated"
24	"honnef.co/go/tools/edit"
25	"honnef.co/go/tools/facts"
26	"honnef.co/go/tools/functions"
27	"honnef.co/go/tools/internal/passes/buildir"
28	"honnef.co/go/tools/internal/sharedcheck"
29	"honnef.co/go/tools/ir"
30	"honnef.co/go/tools/ir/irutil"
31	"honnef.co/go/tools/lint"
32	. "honnef.co/go/tools/lint/lintdsl"
33	"honnef.co/go/tools/pattern"
34	"honnef.co/go/tools/printf"
35	"honnef.co/go/tools/report"
36
37	"golang.org/x/tools/go/analysis"
38	"golang.org/x/tools/go/analysis/passes/inspect"
39	"golang.org/x/tools/go/ast/astutil"
40	"golang.org/x/tools/go/ast/inspector"
41	"golang.org/x/tools/go/types/typeutil"
42)
43
44func checkSortSlice(call *Call) {
45	c := call.Instr.Common().StaticCallee()
46	arg := call.Args[0]
47
48	T := arg.Value.Value.Type().Underlying()
49	switch T.(type) {
50	case *types.Interface:
51		// we don't know.
52		// TODO(dh): if the value is a phi node we can look at its edges
53		if k, ok := arg.Value.Value.(*ir.Const); ok && k.Value == nil {
54			// literal nil, e.g. sort.Sort(nil, ...)
55			arg.Invalid(fmt.Sprintf("cannot call %s on nil literal", c))
56		}
57	case *types.Slice:
58		// this is fine
59	default:
60		// this is not fine
61		arg.Invalid(fmt.Sprintf("%s must only be called on slices, was called on %s", c, T))
62	}
63}
64
65func validRegexp(call *Call) {
66	arg := call.Args[0]
67	err := ValidateRegexp(arg.Value)
68	if err != nil {
69		arg.Invalid(err.Error())
70	}
71}
72
73type runeSlice []rune
74
75func (rs runeSlice) Len() int               { return len(rs) }
76func (rs runeSlice) Less(i int, j int) bool { return rs[i] < rs[j] }
77func (rs runeSlice) Swap(i int, j int)      { rs[i], rs[j] = rs[j], rs[i] }
78
79func utf8Cutset(call *Call) {
80	arg := call.Args[1]
81	if InvalidUTF8(arg.Value) {
82		arg.Invalid(MsgInvalidUTF8)
83	}
84}
85
86func uniqueCutset(call *Call) {
87	arg := call.Args[1]
88	if !UniqueStringCutset(arg.Value) {
89		arg.Invalid(MsgNonUniqueCutset)
90	}
91}
92
93func unmarshalPointer(name string, arg int) CallCheck {
94	return func(call *Call) {
95		if !Pointer(call.Args[arg].Value) {
96			call.Args[arg].Invalid(fmt.Sprintf("%s expects to unmarshal into a pointer, but the provided value is not a pointer", name))
97		}
98	}
99}
100
101func pointlessIntMath(call *Call) {
102	if ConvertedFromInt(call.Args[0].Value) {
103		call.Invalid(fmt.Sprintf("calling %s on a converted integer is pointless", code.CallName(call.Instr.Common())))
104	}
105}
106
107func checkValidHostPort(arg int) CallCheck {
108	return func(call *Call) {
109		if !ValidHostPort(call.Args[arg].Value) {
110			call.Args[arg].Invalid(MsgInvalidHostPort)
111		}
112	}
113}
114
115var (
116	checkRegexpRules = map[string]CallCheck{
117		"regexp.MustCompile": validRegexp,
118		"regexp.Compile":     validRegexp,
119		"regexp.Match":       validRegexp,
120		"regexp.MatchReader": validRegexp,
121		"regexp.MatchString": validRegexp,
122	}
123
124	checkTimeParseRules = map[string]CallCheck{
125		"time.Parse": func(call *Call) {
126			arg := call.Args[Arg("time.Parse.layout")]
127			err := ValidateTimeLayout(arg.Value)
128			if err != nil {
129				arg.Invalid(err.Error())
130			}
131		},
132	}
133
134	checkEncodingBinaryRules = map[string]CallCheck{
135		"encoding/binary.Write": func(call *Call) {
136			arg := call.Args[Arg("encoding/binary.Write.data")]
137			if !CanBinaryMarshal(call.Pass, arg.Value) {
138				arg.Invalid(fmt.Sprintf("value of type %s cannot be used with binary.Write", arg.Value.Value.Type()))
139			}
140		},
141	}
142
143	checkURLsRules = map[string]CallCheck{
144		"net/url.Parse": func(call *Call) {
145			arg := call.Args[Arg("net/url.Parse.rawurl")]
146			err := ValidateURL(arg.Value)
147			if err != nil {
148				arg.Invalid(err.Error())
149			}
150		},
151	}
152
153	checkSyncPoolValueRules = map[string]CallCheck{
154		"(*sync.Pool).Put": func(call *Call) {
155			arg := call.Args[Arg("(*sync.Pool).Put.x")]
156			typ := arg.Value.Value.Type()
157			if !code.IsPointerLike(typ) {
158				arg.Invalid("argument should be pointer-like to avoid allocations")
159			}
160		},
161	}
162
163	checkRegexpFindAllRules = map[string]CallCheck{
164		"(*regexp.Regexp).FindAll":                    RepeatZeroTimes("a FindAll method", 1),
165		"(*regexp.Regexp).FindAllIndex":               RepeatZeroTimes("a FindAll method", 1),
166		"(*regexp.Regexp).FindAllString":              RepeatZeroTimes("a FindAll method", 1),
167		"(*regexp.Regexp).FindAllStringIndex":         RepeatZeroTimes("a FindAll method", 1),
168		"(*regexp.Regexp).FindAllStringSubmatch":      RepeatZeroTimes("a FindAll method", 1),
169		"(*regexp.Regexp).FindAllStringSubmatchIndex": RepeatZeroTimes("a FindAll method", 1),
170		"(*regexp.Regexp).FindAllSubmatch":            RepeatZeroTimes("a FindAll method", 1),
171		"(*regexp.Regexp).FindAllSubmatchIndex":       RepeatZeroTimes("a FindAll method", 1),
172	}
173
174	checkUTF8CutsetRules = map[string]CallCheck{
175		"strings.IndexAny":     utf8Cutset,
176		"strings.LastIndexAny": utf8Cutset,
177		"strings.ContainsAny":  utf8Cutset,
178		"strings.Trim":         utf8Cutset,
179		"strings.TrimLeft":     utf8Cutset,
180		"strings.TrimRight":    utf8Cutset,
181	}
182
183	checkUniqueCutsetRules = map[string]CallCheck{
184		"strings.Trim":      uniqueCutset,
185		"strings.TrimLeft":  uniqueCutset,
186		"strings.TrimRight": uniqueCutset,
187	}
188
189	checkUnmarshalPointerRules = map[string]CallCheck{
190		"encoding/xml.Unmarshal":                unmarshalPointer("xml.Unmarshal", 1),
191		"(*encoding/xml.Decoder).Decode":        unmarshalPointer("Decode", 0),
192		"(*encoding/xml.Decoder).DecodeElement": unmarshalPointer("DecodeElement", 0),
193		"encoding/json.Unmarshal":               unmarshalPointer("json.Unmarshal", 1),
194		"(*encoding/json.Decoder).Decode":       unmarshalPointer("Decode", 0),
195	}
196
197	checkUnbufferedSignalChanRules = map[string]CallCheck{
198		"os/signal.Notify": func(call *Call) {
199			arg := call.Args[Arg("os/signal.Notify.c")]
200			if UnbufferedChannel(arg.Value) {
201				arg.Invalid("the channel used with signal.Notify should be buffered")
202			}
203		},
204	}
205
206	checkMathIntRules = map[string]CallCheck{
207		"math.Ceil":  pointlessIntMath,
208		"math.Floor": pointlessIntMath,
209		"math.IsNaN": pointlessIntMath,
210		"math.Trunc": pointlessIntMath,
211		"math.IsInf": pointlessIntMath,
212	}
213
214	checkStringsReplaceZeroRules = map[string]CallCheck{
215		"strings.Replace": RepeatZeroTimes("strings.Replace", 3),
216		"bytes.Replace":   RepeatZeroTimes("bytes.Replace", 3),
217	}
218
219	checkListenAddressRules = map[string]CallCheck{
220		"net/http.ListenAndServe":    checkValidHostPort(0),
221		"net/http.ListenAndServeTLS": checkValidHostPort(0),
222	}
223
224	checkBytesEqualIPRules = map[string]CallCheck{
225		"bytes.Equal": func(call *Call) {
226			if ConvertedFrom(call.Args[Arg("bytes.Equal.a")].Value, "net.IP") &&
227				ConvertedFrom(call.Args[Arg("bytes.Equal.b")].Value, "net.IP") {
228				call.Invalid("use net.IP.Equal to compare net.IPs, not bytes.Equal")
229			}
230		},
231	}
232
233	checkRegexpMatchLoopRules = map[string]CallCheck{
234		"regexp.Match":       loopedRegexp("regexp.Match"),
235		"regexp.MatchReader": loopedRegexp("regexp.MatchReader"),
236		"regexp.MatchString": loopedRegexp("regexp.MatchString"),
237	}
238
239	checkNoopMarshal = map[string]CallCheck{
240		// TODO(dh): should we really flag XML? Even an empty struct
241		// produces a non-zero amount of data, namely its type name.
242		// Let's see if we encounter any false positives.
243		//
244		// Also, should we flag gob?
245		"encoding/json.Marshal":           checkNoopMarshalImpl(Arg("json.Marshal.v"), "MarshalJSON", "MarshalText"),
246		"encoding/xml.Marshal":            checkNoopMarshalImpl(Arg("xml.Marshal.v"), "MarshalXML", "MarshalText"),
247		"(*encoding/json.Encoder).Encode": checkNoopMarshalImpl(Arg("(*encoding/json.Encoder).Encode.v"), "MarshalJSON", "MarshalText"),
248		"(*encoding/xml.Encoder).Encode":  checkNoopMarshalImpl(Arg("(*encoding/xml.Encoder).Encode.v"), "MarshalXML", "MarshalText"),
249
250		"encoding/json.Unmarshal":         checkNoopMarshalImpl(Arg("json.Unmarshal.v"), "UnmarshalJSON", "UnmarshalText"),
251		"encoding/xml.Unmarshal":          checkNoopMarshalImpl(Arg("xml.Unmarshal.v"), "UnmarshalXML", "UnmarshalText"),
252		"(*encoding/json.Decoder).Decode": checkNoopMarshalImpl(Arg("(*encoding/json.Decoder).Decode.v"), "UnmarshalJSON", "UnmarshalText"),
253		"(*encoding/xml.Decoder).Decode":  checkNoopMarshalImpl(Arg("(*encoding/xml.Decoder).Decode.v"), "UnmarshalXML", "UnmarshalText"),
254	}
255
256	checkUnsupportedMarshal = map[string]CallCheck{
257		"encoding/json.Marshal":           checkUnsupportedMarshalImpl(Arg("json.Marshal.v"), "json", "MarshalJSON", "MarshalText"),
258		"encoding/xml.Marshal":            checkUnsupportedMarshalImpl(Arg("xml.Marshal.v"), "xml", "MarshalXML", "MarshalText"),
259		"(*encoding/json.Encoder).Encode": checkUnsupportedMarshalImpl(Arg("(*encoding/json.Encoder).Encode.v"), "json", "MarshalJSON", "MarshalText"),
260		"(*encoding/xml.Encoder).Encode":  checkUnsupportedMarshalImpl(Arg("(*encoding/xml.Encoder).Encode.v"), "xml", "MarshalXML", "MarshalText"),
261	}
262
263	checkAtomicAlignment = map[string]CallCheck{
264		"sync/atomic.AddInt64":             checkAtomicAlignmentImpl,
265		"sync/atomic.AddUint64":            checkAtomicAlignmentImpl,
266		"sync/atomic.CompareAndSwapInt64":  checkAtomicAlignmentImpl,
267		"sync/atomic.CompareAndSwapUint64": checkAtomicAlignmentImpl,
268		"sync/atomic.LoadInt64":            checkAtomicAlignmentImpl,
269		"sync/atomic.LoadUint64":           checkAtomicAlignmentImpl,
270		"sync/atomic.StoreInt64":           checkAtomicAlignmentImpl,
271		"sync/atomic.StoreUint64":          checkAtomicAlignmentImpl,
272		"sync/atomic.SwapInt64":            checkAtomicAlignmentImpl,
273		"sync/atomic.SwapUint64":           checkAtomicAlignmentImpl,
274	}
275
276	// TODO(dh): detect printf wrappers
277	checkPrintfRules = map[string]CallCheck{
278		"fmt.Errorf":                  func(call *Call) { checkPrintfCall(call, 0, 1) },
279		"fmt.Printf":                  func(call *Call) { checkPrintfCall(call, 0, 1) },
280		"fmt.Sprintf":                 func(call *Call) { checkPrintfCall(call, 0, 1) },
281		"fmt.Fprintf":                 func(call *Call) { checkPrintfCall(call, 1, 2) },
282		"golang.org/x/xerrors.Errorf": func(call *Call) { checkPrintfCall(call, 0, 1) },
283	}
284
285	checkSortSliceRules = map[string]CallCheck{
286		"sort.Slice":         checkSortSlice,
287		"sort.SliceIsSorted": checkSortSlice,
288		"sort.SliceStable":   checkSortSlice,
289	}
290
291	checkWithValueKeyRules = map[string]CallCheck{
292		"context.WithValue": checkWithValueKey,
293	}
294)
295
296func checkPrintfCall(call *Call, fIdx, vIdx int) {
297	f := call.Args[fIdx]
298	var args []ir.Value
299	switch v := call.Args[vIdx].Value.Value.(type) {
300	case *ir.Slice:
301		var ok bool
302		args, ok = irutil.Vararg(v)
303		if !ok {
304			// We don't know what the actual arguments to the function are
305			return
306		}
307	case *ir.Const:
308		// nil, i.e. no arguments
309	default:
310		// We don't know what the actual arguments to the function are
311		return
312	}
313	checkPrintfCallImpl(f, f.Value.Value, args)
314}
315
316type verbFlag int
317
318const (
319	isInt verbFlag = 1 << iota
320	isBool
321	isFP
322	isString
323	isPointer
324	// Verbs that accept "pseudo pointers" will sometimes dereference
325	// non-nil pointers. For example, %x on a non-nil *struct will print the
326	// individual fields, but on a nil pointer it will print the address.
327	isPseudoPointer
328	isSlice
329	isAny
330	noRecurse
331)
332
333var verbs = [...]verbFlag{
334	'b': isPseudoPointer | isInt | isFP,
335	'c': isInt,
336	'd': isPseudoPointer | isInt,
337	'e': isFP,
338	'E': isFP,
339	'f': isFP,
340	'F': isFP,
341	'g': isFP,
342	'G': isFP,
343	'o': isPseudoPointer | isInt,
344	'O': isPseudoPointer | isInt,
345	'p': isSlice | isPointer | noRecurse,
346	'q': isInt | isString,
347	's': isString,
348	't': isBool,
349	'T': isAny,
350	'U': isInt,
351	'v': isAny,
352	'X': isPseudoPointer | isInt | isFP | isString,
353	'x': isPseudoPointer | isInt | isFP | isString,
354}
355
356func checkPrintfCallImpl(carg *Argument, f ir.Value, args []ir.Value) {
357	var msCache *typeutil.MethodSetCache
358	if f.Parent() != nil {
359		msCache = &f.Parent().Prog.MethodSets
360	}
361
362	elem := func(T types.Type, verb rune) ([]types.Type, bool) {
363		if verbs[verb]&noRecurse != 0 {
364			return []types.Type{T}, false
365		}
366		switch T := T.(type) {
367		case *types.Slice:
368			if verbs[verb]&isSlice != 0 {
369				return []types.Type{T}, false
370			}
371			if verbs[verb]&isString != 0 && code.IsType(T.Elem().Underlying(), "byte") {
372				return []types.Type{T}, false
373			}
374			return []types.Type{T.Elem()}, true
375		case *types.Map:
376			key := T.Key()
377			val := T.Elem()
378			return []types.Type{key, val}, true
379		case *types.Struct:
380			out := make([]types.Type, 0, T.NumFields())
381			for i := 0; i < T.NumFields(); i++ {
382				out = append(out, T.Field(i).Type())
383			}
384			return out, true
385		case *types.Array:
386			return []types.Type{T.Elem()}, true
387		default:
388			return []types.Type{T}, false
389		}
390	}
391	isInfo := func(T types.Type, info types.BasicInfo) bool {
392		basic, ok := T.Underlying().(*types.Basic)
393		return ok && basic.Info()&info != 0
394	}
395
396	isStringer := func(T types.Type, ms *types.MethodSet) bool {
397		sel := ms.Lookup(nil, "String")
398		if sel == nil {
399			return false
400		}
401		fn, ok := sel.Obj().(*types.Func)
402		if !ok {
403			// should be unreachable
404			return false
405		}
406		sig := fn.Type().(*types.Signature)
407		if sig.Params().Len() != 0 {
408			return false
409		}
410		if sig.Results().Len() != 1 {
411			return false
412		}
413		if !code.IsType(sig.Results().At(0).Type(), "string") {
414			return false
415		}
416		return true
417	}
418	isError := func(T types.Type, ms *types.MethodSet) bool {
419		sel := ms.Lookup(nil, "Error")
420		if sel == nil {
421			return false
422		}
423		fn, ok := sel.Obj().(*types.Func)
424		if !ok {
425			// should be unreachable
426			return false
427		}
428		sig := fn.Type().(*types.Signature)
429		if sig.Params().Len() != 0 {
430			return false
431		}
432		if sig.Results().Len() != 1 {
433			return false
434		}
435		if !code.IsType(sig.Results().At(0).Type(), "string") {
436			return false
437		}
438		return true
439	}
440
441	isFormatter := func(T types.Type, ms *types.MethodSet) bool {
442		sel := ms.Lookup(nil, "Format")
443		if sel == nil {
444			return false
445		}
446		fn, ok := sel.Obj().(*types.Func)
447		if !ok {
448			// should be unreachable
449			return false
450		}
451		sig := fn.Type().(*types.Signature)
452		if sig.Params().Len() != 2 {
453			return false
454		}
455		// TODO(dh): check the types of the arguments for more
456		// precision
457		if sig.Results().Len() != 0 {
458			return false
459		}
460		return true
461	}
462
463	seen := map[types.Type]bool{}
464	var checkType func(verb rune, T types.Type, top bool) bool
465	checkType = func(verb rune, T types.Type, top bool) bool {
466		if top {
467			for k := range seen {
468				delete(seen, k)
469			}
470		}
471		if seen[T] {
472			return true
473		}
474		seen[T] = true
475		if int(verb) >= len(verbs) {
476			// Unknown verb
477			return true
478		}
479
480		flags := verbs[verb]
481		if flags == 0 {
482			// Unknown verb
483			return true
484		}
485
486		ms := msCache.MethodSet(T)
487		if isFormatter(T, ms) {
488			// the value is responsible for formatting itself
489			return true
490		}
491
492		if flags&isString != 0 && (isStringer(T, ms) || isError(T, ms)) {
493			// Check for stringer early because we're about to dereference
494			return true
495		}
496
497		T = T.Underlying()
498		if flags&(isPointer|isPseudoPointer) == 0 && top {
499			T = code.Dereference(T)
500		}
501		if flags&isPseudoPointer != 0 && top {
502			t := code.Dereference(T)
503			if _, ok := t.Underlying().(*types.Struct); ok {
504				T = t
505			}
506		}
507
508		if _, ok := T.(*types.Interface); ok {
509			// We don't know what's in the interface
510			return true
511		}
512
513		var info types.BasicInfo
514		if flags&isInt != 0 {
515			info |= types.IsInteger
516		}
517		if flags&isBool != 0 {
518			info |= types.IsBoolean
519		}
520		if flags&isFP != 0 {
521			info |= types.IsFloat | types.IsComplex
522		}
523		if flags&isString != 0 {
524			info |= types.IsString
525		}
526
527		if info != 0 && isInfo(T, info) {
528			return true
529		}
530
531		if flags&isString != 0 {
532			isStringyElem := func(typ types.Type) bool {
533				if typ, ok := typ.Underlying().(*types.Basic); ok {
534					return typ.Kind() == types.Byte
535				}
536				return false
537			}
538			switch T := T.(type) {
539			case *types.Slice:
540				if isStringyElem(T.Elem()) {
541					return true
542				}
543			case *types.Array:
544				if isStringyElem(T.Elem()) {
545					return true
546				}
547			}
548			if isStringer(T, ms) || isError(T, ms) {
549				return true
550			}
551		}
552
553		if flags&isPointer != 0 && code.IsPointerLike(T) {
554			return true
555		}
556		if flags&isPseudoPointer != 0 {
557			switch U := T.Underlying().(type) {
558			case *types.Pointer:
559				if !top {
560					return true
561				}
562
563				if _, ok := U.Elem().Underlying().(*types.Struct); !ok {
564					// TODO(dh): can this condition ever be false? For
565					// *T, if T is a struct, we'll already have
566					// dereferenced it, meaning the *types.Pointer
567					// branch couldn't have been taken. For T that
568					// aren't structs, this condition will always
569					// evaluate to true.
570					return true
571				}
572			case *types.Chan, *types.Signature:
573				// Channels and functions are always treated as
574				// pointers and never recursed into.
575				return true
576			case *types.Basic:
577				if U.Kind() == types.UnsafePointer {
578					return true
579				}
580			case *types.Interface:
581				// we will already have bailed if the type is an
582				// interface.
583				panic("unreachable")
584			default:
585				// other pointer-like types, such as maps or slices,
586				// will be printed element-wise.
587			}
588		}
589
590		if flags&isSlice != 0 {
591			if _, ok := T.(*types.Slice); ok {
592				return true
593			}
594		}
595
596		if flags&isAny != 0 {
597			return true
598		}
599
600		elems, ok := elem(T.Underlying(), verb)
601		if !ok {
602			return false
603		}
604		for _, elem := range elems {
605			if !checkType(verb, elem, false) {
606				return false
607			}
608		}
609
610		return true
611	}
612
613	k, ok := f.(*ir.Const)
614	if !ok {
615		return
616	}
617	actions, err := printf.Parse(constant.StringVal(k.Value))
618	if err != nil {
619		carg.Invalid("couldn't parse format string")
620		return
621	}
622
623	ptr := 1
624	hasExplicit := false
625
626	checkStar := func(verb printf.Verb, star printf.Argument) bool {
627		if star, ok := star.(printf.Star); ok {
628			idx := 0
629			if star.Index == -1 {
630				idx = ptr
631				ptr++
632			} else {
633				hasExplicit = true
634				idx = star.Index
635				ptr = star.Index + 1
636			}
637			if idx == 0 {
638				carg.Invalid(fmt.Sprintf("Printf format %s reads invalid arg 0; indices are 1-based", verb.Raw))
639				return false
640			}
641			if idx > len(args) {
642				carg.Invalid(
643					fmt.Sprintf("Printf format %s reads arg #%d, but call has only %d args",
644						verb.Raw, idx, len(args)))
645				return false
646			}
647			if arg, ok := args[idx-1].(*ir.MakeInterface); ok {
648				if !isInfo(arg.X.Type(), types.IsInteger) {
649					carg.Invalid(fmt.Sprintf("Printf format %s reads non-int arg #%d as argument of *", verb.Raw, idx))
650				}
651			}
652		}
653		return true
654	}
655
656	// We only report one problem per format string. Making a
657	// mistake with an index tends to invalidate all future
658	// implicit indices.
659	for _, action := range actions {
660		verb, ok := action.(printf.Verb)
661		if !ok {
662			continue
663		}
664
665		if !checkStar(verb, verb.Width) || !checkStar(verb, verb.Precision) {
666			return
667		}
668
669		off := ptr
670		if verb.Value != -1 {
671			hasExplicit = true
672			off = verb.Value
673		}
674		if off > len(args) {
675			carg.Invalid(
676				fmt.Sprintf("Printf format %s reads arg #%d, but call has only %d args",
677					verb.Raw, off, len(args)))
678			return
679		} else if verb.Value == 0 && verb.Letter != '%' {
680			carg.Invalid(fmt.Sprintf("Printf format %s reads invalid arg 0; indices are 1-based", verb.Raw))
681			return
682		} else if off != 0 {
683			arg, ok := args[off-1].(*ir.MakeInterface)
684			if ok {
685				if !checkType(verb.Letter, arg.X.Type(), true) {
686					carg.Invalid(fmt.Sprintf("Printf format %s has arg #%d of wrong type %s",
687						verb.Raw, ptr, args[ptr-1].(*ir.MakeInterface).X.Type()))
688					return
689				}
690			}
691		}
692
693		switch verb.Value {
694		case -1:
695			// Consume next argument
696			ptr++
697		case 0:
698			// Don't consume any arguments
699		default:
700			ptr = verb.Value + 1
701		}
702	}
703
704	if !hasExplicit && ptr <= len(args) {
705		carg.Invalid(fmt.Sprintf("Printf call needs %d args but has %d args", ptr-1, len(args)))
706	}
707}
708
709func checkAtomicAlignmentImpl(call *Call) {
710	sizes := call.Pass.TypesSizes
711	if sizes.Sizeof(types.Typ[types.Uintptr]) != 4 {
712		// Not running on a 32-bit platform
713		return
714	}
715	v, ok := call.Args[0].Value.Value.(*ir.FieldAddr)
716	if !ok {
717		// TODO(dh): also check indexing into arrays and slices
718		return
719	}
720	T := v.X.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Struct)
721	fields := make([]*types.Var, 0, T.NumFields())
722	for i := 0; i < T.NumFields() && i <= v.Field; i++ {
723		fields = append(fields, T.Field(i))
724	}
725
726	off := sizes.Offsetsof(fields)[v.Field]
727	if off%8 != 0 {
728		msg := fmt.Sprintf("address of non 64-bit aligned field %s passed to %s",
729			T.Field(v.Field).Name(),
730			code.CallName(call.Instr.Common()))
731		call.Invalid(msg)
732	}
733}
734
735func checkNoopMarshalImpl(argN int, meths ...string) CallCheck {
736	return func(call *Call) {
737		if code.IsGenerated(call.Pass, call.Instr.Pos()) {
738			return
739		}
740		arg := call.Args[argN]
741		T := arg.Value.Value.Type()
742		Ts, ok := code.Dereference(T).Underlying().(*types.Struct)
743		if !ok {
744			return
745		}
746		if Ts.NumFields() == 0 {
747			return
748		}
749		fields := code.FlattenFields(Ts)
750		for _, field := range fields {
751			if field.Var.Exported() {
752				return
753			}
754		}
755		// OPT(dh): we could use a method set cache here
756		ms := call.Instr.Parent().Prog.MethodSets.MethodSet(T)
757		// TODO(dh): we're not checking the signature, which can cause false negatives.
758		// This isn't a huge problem, however, since vet complains about incorrect signatures.
759		for _, meth := range meths {
760			if ms.Lookup(nil, meth) != nil {
761				return
762			}
763		}
764		arg.Invalid("struct doesn't have any exported fields, nor custom marshaling")
765	}
766}
767
768func checkUnsupportedMarshalImpl(argN int, tag string, meths ...string) CallCheck {
769	// TODO(dh): flag slices and maps of unsupported types
770	return func(call *Call) {
771		msCache := &call.Instr.Parent().Prog.MethodSets
772
773		arg := call.Args[argN]
774		T := arg.Value.Value.Type()
775		Ts, ok := code.Dereference(T).Underlying().(*types.Struct)
776		if !ok {
777			return
778		}
779		ms := msCache.MethodSet(T)
780		// TODO(dh): we're not checking the signature, which can cause false negatives.
781		// This isn't a huge problem, however, since vet complains about incorrect signatures.
782		for _, meth := range meths {
783			if ms.Lookup(nil, meth) != nil {
784				return
785			}
786		}
787		fields := code.FlattenFields(Ts)
788		for _, field := range fields {
789			if !(field.Var.Exported()) {
790				continue
791			}
792			if reflect.StructTag(field.Tag).Get(tag) == "-" {
793				continue
794			}
795			ms := msCache.MethodSet(field.Var.Type())
796			// TODO(dh): we're not checking the signature, which can cause false negatives.
797			// This isn't a huge problem, however, since vet complains about incorrect signatures.
798			for _, meth := range meths {
799				if ms.Lookup(nil, meth) != nil {
800					return
801				}
802			}
803			switch field.Var.Type().Underlying().(type) {
804			case *types.Chan, *types.Signature:
805				arg.Invalid(fmt.Sprintf("trying to marshal chan or func value, field %s", fieldPath(T, field.Path)))
806			}
807		}
808	}
809}
810
811func fieldPath(start types.Type, indices []int) string {
812	p := start.String()
813	for _, idx := range indices {
814		field := code.Dereference(start).Underlying().(*types.Struct).Field(idx)
815		start = field.Type()
816		p += "." + field.Name()
817	}
818	return p
819}
820
821func isInLoop(b *ir.BasicBlock) bool {
822	sets := functions.FindLoops(b.Parent())
823	for _, set := range sets {
824		if set.Has(b) {
825			return true
826		}
827	}
828	return false
829}
830
831func CheckUntrappableSignal(pass *analysis.Pass) (interface{}, error) {
832	fn := func(node ast.Node) {
833		call := node.(*ast.CallExpr)
834		if !code.IsCallToAnyAST(pass, call,
835			"os/signal.Ignore", "os/signal.Notify", "os/signal.Reset") {
836			return
837		}
838
839		hasSigterm := false
840		for _, arg := range call.Args {
841			if conv, ok := arg.(*ast.CallExpr); ok && isName(pass, conv.Fun, "os.Signal") {
842				arg = conv.Args[0]
843			}
844
845			if isName(pass, arg, "syscall.SIGTERM") {
846				hasSigterm = true
847				break
848			}
849
850		}
851		for i, arg := range call.Args {
852			if conv, ok := arg.(*ast.CallExpr); ok && isName(pass, conv.Fun, "os.Signal") {
853				arg = conv.Args[0]
854			}
855
856			if isName(pass, arg, "os.Kill") || isName(pass, arg, "syscall.SIGKILL") {
857				var fixes []analysis.SuggestedFix
858				if !hasSigterm {
859					nargs := make([]ast.Expr, len(call.Args))
860					for j, a := range call.Args {
861						if i == j {
862							nargs[j] = Selector("syscall", "SIGTERM")
863						} else {
864							nargs[j] = a
865						}
866					}
867					ncall := *call
868					ncall.Args = nargs
869					fixes = append(fixes, edit.Fix(fmt.Sprintf("use syscall.SIGTERM instead of %s", report.Render(pass, arg)), edit.ReplaceWithNode(pass.Fset, call, &ncall)))
870				}
871				nargs := make([]ast.Expr, 0, len(call.Args))
872				for j, a := range call.Args {
873					if i == j {
874						continue
875					}
876					nargs = append(nargs, a)
877				}
878				ncall := *call
879				ncall.Args = nargs
880				fixes = append(fixes, edit.Fix(fmt.Sprintf("remove %s from list of arguments", report.Render(pass, arg)), edit.ReplaceWithNode(pass.Fset, call, &ncall)))
881				report.Report(pass, arg, fmt.Sprintf("%s cannot be trapped (did you mean syscall.SIGTERM?)", report.Render(pass, arg)), report.Fixes(fixes...))
882			}
883			if isName(pass, arg, "syscall.SIGSTOP") {
884				nargs := make([]ast.Expr, 0, len(call.Args)-1)
885				for j, a := range call.Args {
886					if i == j {
887						continue
888					}
889					nargs = append(nargs, a)
890				}
891				ncall := *call
892				ncall.Args = nargs
893				report.Report(pass, arg, "syscall.SIGSTOP cannot be trapped", report.Fixes(edit.Fix("remove syscall.SIGSTOP from list of arguments", edit.ReplaceWithNode(pass.Fset, call, &ncall))))
894			}
895		}
896	}
897	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
898	return nil, nil
899}
900
901func CheckTemplate(pass *analysis.Pass) (interface{}, error) {
902	fn := func(node ast.Node) {
903		call := node.(*ast.CallExpr)
904		var kind string
905		switch code.CallNameAST(pass, call) {
906		case "(*text/template.Template).Parse":
907			kind = "text"
908		case "(*html/template.Template).Parse":
909			kind = "html"
910		default:
911			return
912		}
913		sel := call.Fun.(*ast.SelectorExpr)
914		if !code.IsCallToAnyAST(pass, sel.X, "text/template.New", "html/template.New") {
915			// TODO(dh): this is a cheap workaround for templates with
916			// different delims. A better solution with less false
917			// negatives would use data flow analysis to see where the
918			// template comes from and where it has been
919			return
920		}
921		s, ok := code.ExprToString(pass, call.Args[Arg("(*text/template.Template).Parse.text")])
922		if !ok {
923			return
924		}
925		var err error
926		switch kind {
927		case "text":
928			_, err = texttemplate.New("").Parse(s)
929		case "html":
930			_, err = htmltemplate.New("").Parse(s)
931		}
932		if err != nil {
933			// TODO(dominikh): whitelist other parse errors, if any
934			if strings.Contains(err.Error(), "unexpected") {
935				report.Report(pass, call.Args[Arg("(*text/template.Template).Parse.text")], err.Error())
936			}
937		}
938	}
939	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
940	return nil, nil
941}
942
943var (
944	checkTimeSleepConstantPatternRns = pattern.MustParse(`(BinaryExpr duration "*" (SelectorExpr (Ident "time") (Ident "Nanosecond")))`)
945	checkTimeSleepConstantPatternRs  = pattern.MustParse(`(BinaryExpr duration "*" (SelectorExpr (Ident "time") (Ident "Second")))`)
946)
947
948func CheckTimeSleepConstant(pass *analysis.Pass) (interface{}, error) {
949	fn := func(node ast.Node) {
950		call := node.(*ast.CallExpr)
951		if !code.IsCallToAST(pass, call, "time.Sleep") {
952			return
953		}
954		lit, ok := call.Args[Arg("time.Sleep.d")].(*ast.BasicLit)
955		if !ok {
956			return
957		}
958		n, err := strconv.Atoi(lit.Value)
959		if err != nil {
960			return
961		}
962		if n == 0 || n > 120 {
963			// time.Sleep(0) is a seldom used pattern in concurrency
964			// tests. >120 might be intentional. 120 was chosen
965			// because the user could've meant 2 minutes.
966			return
967		}
968
969		report.Report(pass, lit,
970			fmt.Sprintf("sleeping for %d nanoseconds is probably a bug; be explicit if it isn't", n), report.Fixes(
971				edit.Fix("explicitly use nanoseconds", edit.ReplaceWithPattern(pass, checkTimeSleepConstantPatternRns, pattern.State{"duration": lit}, lit)),
972				edit.Fix("use seconds", edit.ReplaceWithPattern(pass, checkTimeSleepConstantPatternRs, pattern.State{"duration": lit}, lit))))
973	}
974	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
975	return nil, nil
976}
977
978var checkWaitgroupAddQ = pattern.MustParse(`
979	(GoStmt
980		(CallExpr
981			(FuncLit
982				_
983				call@(CallExpr (Function "(*sync.WaitGroup).Add") _):_) _))`)
984
985func CheckWaitgroupAdd(pass *analysis.Pass) (interface{}, error) {
986	fn := func(node ast.Node) {
987		if m, ok := Match(pass, checkWaitgroupAddQ, node); ok {
988			call := m.State["call"].(ast.Node)
989			report.Report(pass, call, fmt.Sprintf("should call %s before starting the goroutine to avoid a race", report.Render(pass, call)))
990		}
991	}
992	code.Preorder(pass, fn, (*ast.GoStmt)(nil))
993	return nil, nil
994}
995
996func CheckInfiniteEmptyLoop(pass *analysis.Pass) (interface{}, error) {
997	fn := func(node ast.Node) {
998		loop := node.(*ast.ForStmt)
999		if len(loop.Body.List) != 0 || loop.Post != nil {
1000			return
1001		}
1002
1003		if loop.Init != nil {
1004			// TODO(dh): this isn't strictly necessary, it just makes
1005			// the check easier.
1006			return
1007		}
1008		// An empty loop is bad news in two cases: 1) The loop has no
1009		// condition. In that case, it's just a loop that spins
1010		// forever and as fast as it can, keeping a core busy. 2) The
1011		// loop condition only consists of variable or field reads and
1012		// operators on those. The only way those could change their
1013		// value is with unsynchronised access, which constitutes a
1014		// data race.
1015		//
1016		// If the condition contains any function calls, its behaviour
1017		// is dynamic and the loop might terminate. Similarly for
1018		// channel receives.
1019
1020		if loop.Cond != nil {
1021			if code.MayHaveSideEffects(pass, loop.Cond, nil) {
1022				return
1023			}
1024			if ident, ok := loop.Cond.(*ast.Ident); ok {
1025				if k, ok := pass.TypesInfo.ObjectOf(ident).(*types.Const); ok {
1026					if !constant.BoolVal(k.Val()) {
1027						// don't flag `for false {}` loops. They're a debug aid.
1028						return
1029					}
1030				}
1031			}
1032			report.Report(pass, loop, "loop condition never changes or has a race condition")
1033		}
1034		report.Report(pass, loop, "this loop will spin, using 100%% CPU", report.ShortRange())
1035	}
1036	code.Preorder(pass, fn, (*ast.ForStmt)(nil))
1037	return nil, nil
1038}
1039
1040func CheckDeferInInfiniteLoop(pass *analysis.Pass) (interface{}, error) {
1041	fn := func(node ast.Node) {
1042		mightExit := false
1043		var defers []ast.Stmt
1044		loop := node.(*ast.ForStmt)
1045		if loop.Cond != nil {
1046			return
1047		}
1048		fn2 := func(node ast.Node) bool {
1049			switch stmt := node.(type) {
1050			case *ast.ReturnStmt:
1051				mightExit = true
1052				return false
1053			case *ast.BranchStmt:
1054				// TODO(dominikh): if this sees a break in a switch or
1055				// select, it doesn't check if it breaks the loop or
1056				// just the select/switch. This causes some false
1057				// negatives.
1058				if stmt.Tok == token.BREAK {
1059					mightExit = true
1060					return false
1061				}
1062			case *ast.DeferStmt:
1063				defers = append(defers, stmt)
1064			case *ast.FuncLit:
1065				// Don't look into function bodies
1066				return false
1067			}
1068			return true
1069		}
1070		ast.Inspect(loop.Body, fn2)
1071		if mightExit {
1072			return
1073		}
1074		for _, stmt := range defers {
1075			report.Report(pass, stmt, "defers in this infinite loop will never run")
1076		}
1077	}
1078	code.Preorder(pass, fn, (*ast.ForStmt)(nil))
1079	return nil, nil
1080}
1081
1082func CheckDubiousDeferInChannelRangeLoop(pass *analysis.Pass) (interface{}, error) {
1083	fn := func(node ast.Node) {
1084		loop := node.(*ast.RangeStmt)
1085		typ := pass.TypesInfo.TypeOf(loop.X)
1086		_, ok := typ.Underlying().(*types.Chan)
1087		if !ok {
1088			return
1089		}
1090		fn2 := func(node ast.Node) bool {
1091			switch stmt := node.(type) {
1092			case *ast.DeferStmt:
1093				report.Report(pass, stmt, "defers in this range loop won't run unless the channel gets closed")
1094			case *ast.FuncLit:
1095				// Don't look into function bodies
1096				return false
1097			}
1098			return true
1099		}
1100		ast.Inspect(loop.Body, fn2)
1101	}
1102	code.Preorder(pass, fn, (*ast.RangeStmt)(nil))
1103	return nil, nil
1104}
1105
1106func CheckTestMainExit(pass *analysis.Pass) (interface{}, error) {
1107	if code.IsGoVersion(pass, 15) {
1108		// Beginning with Go 1.15, the test framework will call
1109		// os.Exit for us.
1110		return nil, nil
1111	}
1112
1113	var (
1114		fnmain    ast.Node
1115		callsExit bool
1116		callsRun  bool
1117		arg       types.Object
1118	)
1119	fn := func(node ast.Node, push bool) bool {
1120		if !push {
1121			if fnmain != nil && node == fnmain {
1122				if !callsExit && callsRun {
1123					report.Report(pass, fnmain, "TestMain should call os.Exit to set exit code")
1124				}
1125				fnmain = nil
1126				callsExit = false
1127				callsRun = false
1128				arg = nil
1129			}
1130			return true
1131		}
1132
1133		switch node := node.(type) {
1134		case *ast.FuncDecl:
1135			if fnmain != nil {
1136				return true
1137			}
1138			if !isTestMain(pass, node) {
1139				return false
1140			}
1141			fnmain = node
1142			arg = pass.TypesInfo.ObjectOf(node.Type.Params.List[0].Names[0])
1143			return true
1144		case *ast.CallExpr:
1145			if code.IsCallToAST(pass, node, "os.Exit") {
1146				callsExit = true
1147				return false
1148			}
1149			sel, ok := node.Fun.(*ast.SelectorExpr)
1150			if !ok {
1151				return true
1152			}
1153			ident, ok := sel.X.(*ast.Ident)
1154			if !ok {
1155				return true
1156			}
1157			if arg != pass.TypesInfo.ObjectOf(ident) {
1158				return true
1159			}
1160			if sel.Sel.Name == "Run" {
1161				callsRun = true
1162				return false
1163			}
1164			return true
1165		default:
1166			ExhaustiveTypeSwitch(node)
1167			return true
1168		}
1169	}
1170	pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Nodes([]ast.Node{(*ast.FuncDecl)(nil), (*ast.CallExpr)(nil)}, fn)
1171	return nil, nil
1172}
1173
1174func isTestMain(pass *analysis.Pass, decl *ast.FuncDecl) bool {
1175	if decl.Name.Name != "TestMain" {
1176		return false
1177	}
1178	if len(decl.Type.Params.List) != 1 {
1179		return false
1180	}
1181	arg := decl.Type.Params.List[0]
1182	if len(arg.Names) != 1 {
1183		return false
1184	}
1185	return code.IsOfType(pass, arg.Type, "*testing.M")
1186}
1187
1188func CheckExec(pass *analysis.Pass) (interface{}, error) {
1189	fn := func(node ast.Node) {
1190		call := node.(*ast.CallExpr)
1191		if !code.IsCallToAST(pass, call, "os/exec.Command") {
1192			return
1193		}
1194		val, ok := code.ExprToString(pass, call.Args[Arg("os/exec.Command.name")])
1195		if !ok {
1196			return
1197		}
1198		if !strings.Contains(val, " ") || strings.Contains(val, `\`) || strings.Contains(val, "/") {
1199			return
1200		}
1201		report.Report(pass, call.Args[Arg("os/exec.Command.name")],
1202			"first argument to exec.Command looks like a shell command, but a program name or path are expected")
1203	}
1204	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
1205	return nil, nil
1206}
1207
1208func CheckLoopEmptyDefault(pass *analysis.Pass) (interface{}, error) {
1209	fn := func(node ast.Node) {
1210		loop := node.(*ast.ForStmt)
1211		if len(loop.Body.List) != 1 || loop.Cond != nil || loop.Init != nil {
1212			return
1213		}
1214		sel, ok := loop.Body.List[0].(*ast.SelectStmt)
1215		if !ok {
1216			return
1217		}
1218		for _, c := range sel.Body.List {
1219			// FIXME this leaves behind an empty line, and possibly
1220			// comments in the default branch. We can't easily fix
1221			// either.
1222			if comm, ok := c.(*ast.CommClause); ok && comm.Comm == nil && len(comm.Body) == 0 {
1223				report.Report(pass, comm, "should not have an empty default case in a for+select loop; the loop will spin",
1224					report.Fixes(edit.Fix("remove empty default branch", edit.Delete(comm))))
1225				// there can only be one default case
1226				break
1227			}
1228		}
1229	}
1230	code.Preorder(pass, fn, (*ast.ForStmt)(nil))
1231	return nil, nil
1232}
1233
1234func CheckLhsRhsIdentical(pass *analysis.Pass) (interface{}, error) {
1235	var isFloat func(T types.Type) bool
1236	isFloat = func(T types.Type) bool {
1237		switch T := T.Underlying().(type) {
1238		case *types.Basic:
1239			kind := T.Kind()
1240			return kind == types.Float32 || kind == types.Float64
1241		case *types.Array:
1242			return isFloat(T.Elem())
1243		case *types.Struct:
1244			for i := 0; i < T.NumFields(); i++ {
1245				if !isFloat(T.Field(i).Type()) {
1246					return false
1247				}
1248			}
1249			return true
1250		default:
1251			return false
1252		}
1253	}
1254
1255	// TODO(dh): this check ignores the existence of side-effects and
1256	// happily flags fn() == fn() – so far, we've had nobody complain
1257	// about a false positive, and it's caught several bugs in real
1258	// code.
1259	fn := func(node ast.Node) {
1260		op := node.(*ast.BinaryExpr)
1261		switch op.Op {
1262		case token.EQL, token.NEQ:
1263			if isFloat(pass.TypesInfo.TypeOf(op.X)) {
1264				// f == f and f != f might be used to check for NaN
1265				return
1266			}
1267		case token.SUB, token.QUO, token.AND, token.REM, token.OR, token.XOR, token.AND_NOT,
1268			token.LAND, token.LOR, token.LSS, token.GTR, token.LEQ, token.GEQ:
1269		default:
1270			// For some ops, such as + and *, it can make sense to
1271			// have identical operands
1272			return
1273		}
1274
1275		if reflect.TypeOf(op.X) != reflect.TypeOf(op.Y) {
1276			return
1277		}
1278		if report.Render(pass, op.X) != report.Render(pass, op.Y) {
1279			return
1280		}
1281		l1, ok1 := op.X.(*ast.BasicLit)
1282		l2, ok2 := op.Y.(*ast.BasicLit)
1283		if ok1 && ok2 && l1.Kind == token.INT && l2.Kind == l1.Kind && l1.Value == "0" && l2.Value == l1.Value && code.IsGenerated(pass, l1.Pos()) {
1284			// cgo generates the following function call:
1285			// _cgoCheckPointer(_cgoBase0, 0 == 0) – it uses 0 == 0
1286			// instead of true in case the user shadowed the
1287			// identifier. Ideally we'd restrict this exception to
1288			// calls of _cgoCheckPointer, but it's not worth the
1289			// hassle of keeping track of the stack. <lit> <op> <lit>
1290			// are very rare to begin with, and we're mostly checking
1291			// for them to catch typos such as 1 == 1 where the user
1292			// meant to type i == 1. The odds of a false negative for
1293			// 0 == 0 are slim.
1294			return
1295		}
1296		report.Report(pass, op, fmt.Sprintf("identical expressions on the left and right side of the '%s' operator", op.Op))
1297	}
1298	code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
1299	return nil, nil
1300}
1301
1302func CheckScopedBreak(pass *analysis.Pass) (interface{}, error) {
1303	fn := func(node ast.Node) {
1304		var body *ast.BlockStmt
1305		switch node := node.(type) {
1306		case *ast.ForStmt:
1307			body = node.Body
1308		case *ast.RangeStmt:
1309			body = node.Body
1310		default:
1311			ExhaustiveTypeSwitch(node)
1312		}
1313		for _, stmt := range body.List {
1314			var blocks [][]ast.Stmt
1315			switch stmt := stmt.(type) {
1316			case *ast.SwitchStmt:
1317				for _, c := range stmt.Body.List {
1318					blocks = append(blocks, c.(*ast.CaseClause).Body)
1319				}
1320			case *ast.SelectStmt:
1321				for _, c := range stmt.Body.List {
1322					blocks = append(blocks, c.(*ast.CommClause).Body)
1323				}
1324			default:
1325				continue
1326			}
1327
1328			for _, body := range blocks {
1329				if len(body) == 0 {
1330					continue
1331				}
1332				lasts := []ast.Stmt{body[len(body)-1]}
1333				// TODO(dh): unfold all levels of nested block
1334				// statements, not just a single level if statement
1335				if ifs, ok := lasts[0].(*ast.IfStmt); ok {
1336					if len(ifs.Body.List) == 0 {
1337						continue
1338					}
1339					lasts[0] = ifs.Body.List[len(ifs.Body.List)-1]
1340
1341					if block, ok := ifs.Else.(*ast.BlockStmt); ok {
1342						if len(block.List) != 0 {
1343							lasts = append(lasts, block.List[len(block.List)-1])
1344						}
1345					}
1346				}
1347				for _, last := range lasts {
1348					branch, ok := last.(*ast.BranchStmt)
1349					if !ok || branch.Tok != token.BREAK || branch.Label != nil {
1350						continue
1351					}
1352					report.Report(pass, branch, "ineffective break statement. Did you mean to break out of the outer loop?")
1353				}
1354			}
1355		}
1356	}
1357	code.Preorder(pass, fn, (*ast.ForStmt)(nil), (*ast.RangeStmt)(nil))
1358	return nil, nil
1359}
1360
1361func CheckUnsafePrintf(pass *analysis.Pass) (interface{}, error) {
1362	fn := func(node ast.Node) {
1363		call := node.(*ast.CallExpr)
1364		name := code.CallNameAST(pass, call)
1365		var arg int
1366
1367		switch name {
1368		case "fmt.Printf", "fmt.Sprintf", "log.Printf":
1369			arg = Arg("fmt.Printf.format")
1370		case "fmt.Fprintf":
1371			arg = Arg("fmt.Fprintf.format")
1372		default:
1373			return
1374		}
1375		if len(call.Args) != arg+1 {
1376			return
1377		}
1378		switch call.Args[arg].(type) {
1379		case *ast.CallExpr, *ast.Ident:
1380		default:
1381			return
1382		}
1383
1384		alt := name[:len(name)-1]
1385		report.Report(pass, call,
1386			"printf-style function with dynamic format string and no further arguments should use print-style function instead",
1387			report.Fixes(edit.Fix(fmt.Sprintf("use %s instead of %s", alt, name), edit.ReplaceWithString(pass.Fset, call.Fun, alt))))
1388	}
1389	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
1390	return nil, nil
1391}
1392
1393func CheckEarlyDefer(pass *analysis.Pass) (interface{}, error) {
1394	fn := func(node ast.Node) {
1395		block := node.(*ast.BlockStmt)
1396		if len(block.List) < 2 {
1397			return
1398		}
1399		for i, stmt := range block.List {
1400			if i == len(block.List)-1 {
1401				break
1402			}
1403			assign, ok := stmt.(*ast.AssignStmt)
1404			if !ok {
1405				continue
1406			}
1407			if len(assign.Rhs) != 1 {
1408				continue
1409			}
1410			if len(assign.Lhs) < 2 {
1411				continue
1412			}
1413			if lhs, ok := assign.Lhs[len(assign.Lhs)-1].(*ast.Ident); ok && lhs.Name == "_" {
1414				continue
1415			}
1416			call, ok := assign.Rhs[0].(*ast.CallExpr)
1417			if !ok {
1418				continue
1419			}
1420			sig, ok := pass.TypesInfo.TypeOf(call.Fun).(*types.Signature)
1421			if !ok {
1422				continue
1423			}
1424			if sig.Results().Len() < 2 {
1425				continue
1426			}
1427			last := sig.Results().At(sig.Results().Len() - 1)
1428			// FIXME(dh): check that it's error from universe, not
1429			// another type of the same name
1430			if last.Type().String() != "error" {
1431				continue
1432			}
1433			lhs, ok := assign.Lhs[0].(*ast.Ident)
1434			if !ok {
1435				continue
1436			}
1437			def, ok := block.List[i+1].(*ast.DeferStmt)
1438			if !ok {
1439				continue
1440			}
1441			sel, ok := def.Call.Fun.(*ast.SelectorExpr)
1442			if !ok {
1443				continue
1444			}
1445			ident, ok := selectorX(sel).(*ast.Ident)
1446			if !ok {
1447				continue
1448			}
1449			if ident.Obj != lhs.Obj {
1450				continue
1451			}
1452			if sel.Sel.Name != "Close" {
1453				continue
1454			}
1455			report.Report(pass, def, fmt.Sprintf("should check returned error before deferring %s", report.Render(pass, def.Call)))
1456		}
1457	}
1458	code.Preorder(pass, fn, (*ast.BlockStmt)(nil))
1459	return nil, nil
1460}
1461
1462func selectorX(sel *ast.SelectorExpr) ast.Node {
1463	switch x := sel.X.(type) {
1464	case *ast.SelectorExpr:
1465		return selectorX(x)
1466	default:
1467		return x
1468	}
1469}
1470
1471func CheckEmptyCriticalSection(pass *analysis.Pass) (interface{}, error) {
1472	if pass.Pkg.Path() == "sync_test" {
1473		// exception for the sync package's tests
1474		return nil, nil
1475	}
1476
1477	// Initially it might seem like this check would be easier to
1478	// implement using IR. After all, we're only checking for two
1479	// consecutive method calls. In reality, however, there may be any
1480	// number of other instructions between the lock and unlock, while
1481	// still constituting an empty critical section. For example,
1482	// given `m.x().Lock(); m.x().Unlock()`, there will be a call to
1483	// x(). In the AST-based approach, this has a tiny potential for a
1484	// false positive (the second call to x might be doing work that
1485	// is protected by the mutex). In an IR-based approach, however,
1486	// it would miss a lot of real bugs.
1487
1488	mutexParams := func(s ast.Stmt) (x ast.Expr, funcName string, ok bool) {
1489		expr, ok := s.(*ast.ExprStmt)
1490		if !ok {
1491			return nil, "", false
1492		}
1493		call, ok := expr.X.(*ast.CallExpr)
1494		if !ok {
1495			return nil, "", false
1496		}
1497		sel, ok := call.Fun.(*ast.SelectorExpr)
1498		if !ok {
1499			return nil, "", false
1500		}
1501
1502		fn, ok := pass.TypesInfo.ObjectOf(sel.Sel).(*types.Func)
1503		if !ok {
1504			return nil, "", false
1505		}
1506		sig := fn.Type().(*types.Signature)
1507		if sig.Params().Len() != 0 || sig.Results().Len() != 0 {
1508			return nil, "", false
1509		}
1510
1511		return sel.X, fn.Name(), true
1512	}
1513
1514	fn := func(node ast.Node) {
1515		block := node.(*ast.BlockStmt)
1516		if len(block.List) < 2 {
1517			return
1518		}
1519		for i := range block.List[:len(block.List)-1] {
1520			sel1, method1, ok1 := mutexParams(block.List[i])
1521			sel2, method2, ok2 := mutexParams(block.List[i+1])
1522
1523			if !ok1 || !ok2 || report.Render(pass, sel1) != report.Render(pass, sel2) {
1524				continue
1525			}
1526			if (method1 == "Lock" && method2 == "Unlock") ||
1527				(method1 == "RLock" && method2 == "RUnlock") {
1528				report.Report(pass, block.List[i+1], "empty critical section")
1529			}
1530		}
1531	}
1532	code.Preorder(pass, fn, (*ast.BlockStmt)(nil))
1533	return nil, nil
1534}
1535
1536var (
1537	// cgo produces code like fn(&*_Cvar_kSomeCallbacks) which we don't
1538	// want to flag.
1539	cgoIdent               = regexp.MustCompile(`^_C(func|var)_.+$`)
1540	checkIneffectiveCopyQ1 = pattern.MustParse(`(UnaryExpr "&" (StarExpr obj))`)
1541	checkIneffectiveCopyQ2 = pattern.MustParse(`(StarExpr (UnaryExpr "&" _))`)
1542)
1543
1544func CheckIneffectiveCopy(pass *analysis.Pass) (interface{}, error) {
1545	fn := func(node ast.Node) {
1546		if m, ok := Match(pass, checkIneffectiveCopyQ1, node); ok {
1547			if ident, ok := m.State["obj"].(*ast.Ident); !ok || !cgoIdent.MatchString(ident.Name) {
1548				report.Report(pass, node, "&*x will be simplified to x. It will not copy x.")
1549			}
1550		} else if _, ok := Match(pass, checkIneffectiveCopyQ2, node); ok {
1551			report.Report(pass, node, "*&x will be simplified to x. It will not copy x.")
1552		}
1553	}
1554	code.Preorder(pass, fn, (*ast.UnaryExpr)(nil), (*ast.StarExpr)(nil))
1555	return nil, nil
1556}
1557
1558func CheckCanonicalHeaderKey(pass *analysis.Pass) (interface{}, error) {
1559	fn := func(node ast.Node, push bool) bool {
1560		if !push {
1561			return false
1562		}
1563		assign, ok := node.(*ast.AssignStmt)
1564		if ok {
1565			// TODO(dh): This risks missing some Header reads, for
1566			// example in `h1["foo"] = h2["foo"]` – these edge
1567			// cases are probably rare enough to ignore for now.
1568			for _, expr := range assign.Lhs {
1569				op, ok := expr.(*ast.IndexExpr)
1570				if !ok {
1571					continue
1572				}
1573				if code.IsOfType(pass, op.X, "net/http.Header") {
1574					return false
1575				}
1576			}
1577			return true
1578		}
1579		op, ok := node.(*ast.IndexExpr)
1580		if !ok {
1581			return true
1582		}
1583		if !code.IsOfType(pass, op.X, "net/http.Header") {
1584			return true
1585		}
1586		s, ok := code.ExprToString(pass, op.Index)
1587		if !ok {
1588			return true
1589		}
1590		canonical := http.CanonicalHeaderKey(s)
1591		if s == canonical {
1592			return true
1593		}
1594		var fix analysis.SuggestedFix
1595		switch op.Index.(type) {
1596		case *ast.BasicLit:
1597			fix = edit.Fix("canonicalize header key", edit.ReplaceWithString(pass.Fset, op.Index, strconv.Quote(canonical)))
1598		case *ast.Ident:
1599			call := &ast.CallExpr{
1600				Fun:  Selector("http", "CanonicalHeaderKey"),
1601				Args: []ast.Expr{op.Index},
1602			}
1603			fix = edit.Fix("wrap in http.CanonicalHeaderKey", edit.ReplaceWithNode(pass.Fset, op.Index, call))
1604		}
1605		msg := fmt.Sprintf("keys in http.Header are canonicalized, %q is not canonical; fix the constant or use http.CanonicalHeaderKey", s)
1606		if fix.Message != "" {
1607			report.Report(pass, op, msg, report.Fixes(fix))
1608		} else {
1609			report.Report(pass, op, msg)
1610		}
1611		return true
1612	}
1613	pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Nodes([]ast.Node{(*ast.AssignStmt)(nil), (*ast.IndexExpr)(nil)}, fn)
1614	return nil, nil
1615}
1616
1617func CheckBenchmarkN(pass *analysis.Pass) (interface{}, error) {
1618	fn := func(node ast.Node) {
1619		assign := node.(*ast.AssignStmt)
1620		if len(assign.Lhs) != 1 || len(assign.Rhs) != 1 {
1621			return
1622		}
1623		sel, ok := assign.Lhs[0].(*ast.SelectorExpr)
1624		if !ok {
1625			return
1626		}
1627		if sel.Sel.Name != "N" {
1628			return
1629		}
1630		if !code.IsOfType(pass, sel.X, "*testing.B") {
1631			return
1632		}
1633		report.Report(pass, assign, fmt.Sprintf("should not assign to %s", report.Render(pass, sel)))
1634	}
1635	code.Preorder(pass, fn, (*ast.AssignStmt)(nil))
1636	return nil, nil
1637}
1638
1639func CheckUnreadVariableValues(pass *analysis.Pass) (interface{}, error) {
1640	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
1641		if code.IsExample(fn) {
1642			continue
1643		}
1644		node := fn.Source()
1645		if node == nil {
1646			continue
1647		}
1648		if gen, ok := code.Generator(pass, node.Pos()); ok && gen == facts.Goyacc {
1649			// Don't flag unused values in code generated by goyacc.
1650			// There may be hundreds of those due to the way the state
1651			// machine is constructed.
1652			continue
1653		}
1654
1655		switchTags := map[ir.Value]struct{}{}
1656		ast.Inspect(node, func(node ast.Node) bool {
1657			s, ok := node.(*ast.SwitchStmt)
1658			if !ok {
1659				return true
1660			}
1661			v, _ := fn.ValueForExpr(s.Tag)
1662			switchTags[v] = struct{}{}
1663			return true
1664		})
1665
1666		// OPT(dh): don't use a map, possibly use a bitset
1667		var hasUse func(v ir.Value, seen map[ir.Value]struct{}) bool
1668		hasUse = func(v ir.Value, seen map[ir.Value]struct{}) bool {
1669			if _, ok := seen[v]; ok {
1670				return false
1671			}
1672			if _, ok := switchTags[v]; ok {
1673				return true
1674			}
1675			refs := v.Referrers()
1676			if refs == nil {
1677				// TODO investigate why refs can be nil
1678				return true
1679			}
1680			for _, ref := range *refs {
1681				switch ref := ref.(type) {
1682				case *ir.DebugRef:
1683				case *ir.Sigma:
1684					if seen == nil {
1685						seen = map[ir.Value]struct{}{}
1686					}
1687					seen[v] = struct{}{}
1688					if hasUse(ref, seen) {
1689						return true
1690					}
1691				case *ir.Phi:
1692					if seen == nil {
1693						seen = map[ir.Value]struct{}{}
1694					}
1695					seen[v] = struct{}{}
1696					if hasUse(ref, seen) {
1697						return true
1698					}
1699				default:
1700					return true
1701				}
1702			}
1703			return false
1704		}
1705
1706		ast.Inspect(node, func(node ast.Node) bool {
1707			assign, ok := node.(*ast.AssignStmt)
1708			if !ok {
1709				return true
1710			}
1711			if len(assign.Lhs) > 1 && len(assign.Rhs) == 1 {
1712				// Either a function call with multiple return values,
1713				// or a comma-ok assignment
1714
1715				val, _ := fn.ValueForExpr(assign.Rhs[0])
1716				if val == nil {
1717					return true
1718				}
1719				refs := val.Referrers()
1720				if refs == nil {
1721					return true
1722				}
1723				for _, ref := range *refs {
1724					ex, ok := ref.(*ir.Extract)
1725					if !ok {
1726						continue
1727					}
1728					if !hasUse(ex, nil) {
1729						lhs := assign.Lhs[ex.Index]
1730						if ident, ok := lhs.(*ast.Ident); !ok || ok && ident.Name == "_" {
1731							continue
1732						}
1733						report.Report(pass, assign, fmt.Sprintf("this value of %s is never used", lhs))
1734					}
1735				}
1736				return true
1737			}
1738			for i, lhs := range assign.Lhs {
1739				rhs := assign.Rhs[i]
1740				if ident, ok := lhs.(*ast.Ident); !ok || ok && ident.Name == "_" {
1741					continue
1742				}
1743				val, _ := fn.ValueForExpr(rhs)
1744				if val == nil {
1745					continue
1746				}
1747
1748				if _, ok := val.(*ir.Const); ok {
1749					// a zero-valued constant, for example in 'foo := []string(nil)'
1750					continue
1751				}
1752				if !hasUse(val, nil) {
1753					report.Report(pass, assign, fmt.Sprintf("this value of %s is never used", lhs))
1754				}
1755			}
1756			return true
1757		})
1758	}
1759	return nil, nil
1760}
1761
1762func CheckPredeterminedBooleanExprs(pass *analysis.Pass) (interface{}, error) {
1763	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
1764		for _, block := range fn.Blocks {
1765			for _, ins := range block.Instrs {
1766				binop, ok := ins.(*ir.BinOp)
1767				if !ok {
1768					continue
1769				}
1770				switch binop.Op {
1771				case token.GTR, token.LSS, token.EQL, token.NEQ, token.LEQ, token.GEQ:
1772				default:
1773					continue
1774				}
1775
1776				xs, ok1 := consts(binop.X, nil, nil)
1777				ys, ok2 := consts(binop.Y, nil, nil)
1778				if !ok1 || !ok2 || len(xs) == 0 || len(ys) == 0 {
1779					continue
1780				}
1781
1782				trues := 0
1783				for _, x := range xs {
1784					for _, y := range ys {
1785						if x.Value == nil {
1786							if y.Value == nil {
1787								trues++
1788							}
1789							continue
1790						}
1791						if constant.Compare(x.Value, binop.Op, y.Value) {
1792							trues++
1793						}
1794					}
1795				}
1796				b := trues != 0
1797				if trues == 0 || trues == len(xs)*len(ys) {
1798					report.Report(pass, binop, fmt.Sprintf("binary expression is always %t for all possible values (%s %s %s)", b, xs, binop.Op, ys))
1799				}
1800			}
1801		}
1802	}
1803	return nil, nil
1804}
1805
1806func CheckNilMaps(pass *analysis.Pass) (interface{}, error) {
1807	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
1808		for _, block := range fn.Blocks {
1809			for _, ins := range block.Instrs {
1810				mu, ok := ins.(*ir.MapUpdate)
1811				if !ok {
1812					continue
1813				}
1814				c, ok := mu.Map.(*ir.Const)
1815				if !ok {
1816					continue
1817				}
1818				if c.Value != nil {
1819					continue
1820				}
1821				report.Report(pass, mu, "assignment to nil map")
1822			}
1823		}
1824	}
1825	return nil, nil
1826}
1827
1828func CheckExtremeComparison(pass *analysis.Pass) (interface{}, error) {
1829	isobj := func(expr ast.Expr, name string) bool {
1830		sel, ok := expr.(*ast.SelectorExpr)
1831		if !ok {
1832			return false
1833		}
1834		return code.IsObject(pass.TypesInfo.ObjectOf(sel.Sel), name)
1835	}
1836
1837	fn := func(node ast.Node) {
1838		expr := node.(*ast.BinaryExpr)
1839		tx := pass.TypesInfo.TypeOf(expr.X)
1840		basic, ok := tx.Underlying().(*types.Basic)
1841		if !ok {
1842			return
1843		}
1844
1845		var max string
1846		var min string
1847
1848		switch basic.Kind() {
1849		case types.Uint8:
1850			max = "math.MaxUint8"
1851		case types.Uint16:
1852			max = "math.MaxUint16"
1853		case types.Uint32:
1854			max = "math.MaxUint32"
1855		case types.Uint64:
1856			max = "math.MaxUint64"
1857		case types.Uint:
1858			max = "math.MaxUint64"
1859
1860		case types.Int8:
1861			min = "math.MinInt8"
1862			max = "math.MaxInt8"
1863		case types.Int16:
1864			min = "math.MinInt16"
1865			max = "math.MaxInt16"
1866		case types.Int32:
1867			min = "math.MinInt32"
1868			max = "math.MaxInt32"
1869		case types.Int64:
1870			min = "math.MinInt64"
1871			max = "math.MaxInt64"
1872		case types.Int:
1873			min = "math.MinInt64"
1874			max = "math.MaxInt64"
1875		}
1876
1877		if (expr.Op == token.GTR || expr.Op == token.GEQ) && isobj(expr.Y, max) ||
1878			(expr.Op == token.LSS || expr.Op == token.LEQ) && isobj(expr.X, max) {
1879			report.Report(pass, expr, fmt.Sprintf("no value of type %s is greater than %s", basic, max))
1880		}
1881		if expr.Op == token.LEQ && isobj(expr.Y, max) ||
1882			expr.Op == token.GEQ && isobj(expr.X, max) {
1883			report.Report(pass, expr, fmt.Sprintf("every value of type %s is <= %s", basic, max))
1884		}
1885
1886		if (basic.Info() & types.IsUnsigned) != 0 {
1887			if (expr.Op == token.LSS && code.IsIntLiteral(expr.Y, "0")) ||
1888				(expr.Op == token.GTR && code.IsIntLiteral(expr.X, "0")) {
1889				report.Report(pass, expr, fmt.Sprintf("no value of type %s is less than 0", basic))
1890			}
1891			if expr.Op == token.GEQ && code.IsIntLiteral(expr.Y, "0") ||
1892				expr.Op == token.LEQ && code.IsIntLiteral(expr.X, "0") {
1893				report.Report(pass, expr, fmt.Sprintf("every value of type %s is >= 0", basic))
1894			}
1895		} else {
1896			if (expr.Op == token.LSS || expr.Op == token.LEQ) && isobj(expr.Y, min) ||
1897				(expr.Op == token.GTR || expr.Op == token.GEQ) && isobj(expr.X, min) {
1898				report.Report(pass, expr, fmt.Sprintf("no value of type %s is less than %s", basic, min))
1899			}
1900			if expr.Op == token.GEQ && isobj(expr.Y, min) ||
1901				expr.Op == token.LEQ && isobj(expr.X, min) {
1902				report.Report(pass, expr, fmt.Sprintf("every value of type %s is >= %s", basic, min))
1903			}
1904		}
1905
1906	}
1907	code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
1908	return nil, nil
1909}
1910
1911func consts(val ir.Value, out []*ir.Const, visitedPhis map[string]bool) ([]*ir.Const, bool) {
1912	if visitedPhis == nil {
1913		visitedPhis = map[string]bool{}
1914	}
1915	var ok bool
1916	switch val := val.(type) {
1917	case *ir.Phi:
1918		if visitedPhis[val.Name()] {
1919			break
1920		}
1921		visitedPhis[val.Name()] = true
1922		vals := val.Operands(nil)
1923		for _, phival := range vals {
1924			out, ok = consts(*phival, out, visitedPhis)
1925			if !ok {
1926				return nil, false
1927			}
1928		}
1929	case *ir.Const:
1930		out = append(out, val)
1931	case *ir.Convert:
1932		out, ok = consts(val.X, out, visitedPhis)
1933		if !ok {
1934			return nil, false
1935		}
1936	default:
1937		return nil, false
1938	}
1939	if len(out) < 2 {
1940		return out, true
1941	}
1942	uniq := []*ir.Const{out[0]}
1943	for _, val := range out[1:] {
1944		if val.Value == uniq[len(uniq)-1].Value {
1945			continue
1946		}
1947		uniq = append(uniq, val)
1948	}
1949	return uniq, true
1950}
1951
1952func CheckLoopCondition(pass *analysis.Pass) (interface{}, error) {
1953	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
1954		cb := func(node ast.Node) bool {
1955			loop, ok := node.(*ast.ForStmt)
1956			if !ok {
1957				return true
1958			}
1959			if loop.Init == nil || loop.Cond == nil || loop.Post == nil {
1960				return true
1961			}
1962			init, ok := loop.Init.(*ast.AssignStmt)
1963			if !ok || len(init.Lhs) != 1 || len(init.Rhs) != 1 {
1964				return true
1965			}
1966			cond, ok := loop.Cond.(*ast.BinaryExpr)
1967			if !ok {
1968				return true
1969			}
1970			x, ok := cond.X.(*ast.Ident)
1971			if !ok {
1972				return true
1973			}
1974			lhs, ok := init.Lhs[0].(*ast.Ident)
1975			if !ok {
1976				return true
1977			}
1978			if x.Obj != lhs.Obj {
1979				return true
1980			}
1981			if _, ok := loop.Post.(*ast.IncDecStmt); !ok {
1982				return true
1983			}
1984
1985			v, isAddr := fn.ValueForExpr(cond.X)
1986			if v == nil || isAddr {
1987				return true
1988			}
1989			switch v := v.(type) {
1990			case *ir.Phi:
1991				ops := v.Operands(nil)
1992				if len(ops) != 2 {
1993					return true
1994				}
1995				_, ok := (*ops[0]).(*ir.Const)
1996				if !ok {
1997					return true
1998				}
1999				sigma, ok := (*ops[1]).(*ir.Sigma)
2000				if !ok {
2001					return true
2002				}
2003				if sigma.X != v {
2004					return true
2005				}
2006			case *ir.Load:
2007				return true
2008			}
2009			report.Report(pass, cond, "variable in loop condition never changes")
2010
2011			return true
2012		}
2013		Inspect(fn.Source(), cb)
2014	}
2015	return nil, nil
2016}
2017
2018func CheckArgOverwritten(pass *analysis.Pass) (interface{}, error) {
2019	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2020		cb := func(node ast.Node) bool {
2021			var typ *ast.FuncType
2022			var body *ast.BlockStmt
2023			switch fn := node.(type) {
2024			case *ast.FuncDecl:
2025				typ = fn.Type
2026				body = fn.Body
2027			case *ast.FuncLit:
2028				typ = fn.Type
2029				body = fn.Body
2030			}
2031			if body == nil {
2032				return true
2033			}
2034			if len(typ.Params.List) == 0 {
2035				return true
2036			}
2037			for _, field := range typ.Params.List {
2038				for _, arg := range field.Names {
2039					obj := pass.TypesInfo.ObjectOf(arg)
2040					var irobj *ir.Parameter
2041					for _, param := range fn.Params {
2042						if param.Object() == obj {
2043							irobj = param
2044							break
2045						}
2046					}
2047					if irobj == nil {
2048						continue
2049					}
2050					refs := irobj.Referrers()
2051					if refs == nil {
2052						continue
2053					}
2054					if len(code.FilterDebug(*refs)) != 0 {
2055						continue
2056					}
2057
2058					var assignment ast.Node
2059					ast.Inspect(body, func(node ast.Node) bool {
2060						if assignment != nil {
2061							return false
2062						}
2063						assign, ok := node.(*ast.AssignStmt)
2064						if !ok {
2065							return true
2066						}
2067						for _, lhs := range assign.Lhs {
2068							ident, ok := lhs.(*ast.Ident)
2069							if !ok {
2070								continue
2071							}
2072							if pass.TypesInfo.ObjectOf(ident) == obj {
2073								assignment = assign
2074								return false
2075							}
2076						}
2077						return true
2078					})
2079					if assignment != nil {
2080						report.Report(pass, arg, fmt.Sprintf("argument %s is overwritten before first use", arg),
2081							report.Related(assignment, fmt.Sprintf("assignment to %s", arg)))
2082					}
2083				}
2084			}
2085			return true
2086		}
2087		Inspect(fn.Source(), cb)
2088	}
2089	return nil, nil
2090}
2091
2092func CheckIneffectiveLoop(pass *analysis.Pass) (interface{}, error) {
2093	// This check detects some, but not all unconditional loop exits.
2094	// We give up in the following cases:
2095	//
2096	// - a goto anywhere in the loop. The goto might skip over our
2097	// return, and we don't check that it doesn't.
2098	//
2099	// - any nested, unlabelled continue, even if it is in another
2100	// loop or closure.
2101	fn := func(node ast.Node) {
2102		var body *ast.BlockStmt
2103		switch fn := node.(type) {
2104		case *ast.FuncDecl:
2105			body = fn.Body
2106		case *ast.FuncLit:
2107			body = fn.Body
2108		default:
2109			ExhaustiveTypeSwitch(node)
2110		}
2111		if body == nil {
2112			return
2113		}
2114		labels := map[*ast.Object]ast.Stmt{}
2115		ast.Inspect(body, func(node ast.Node) bool {
2116			label, ok := node.(*ast.LabeledStmt)
2117			if !ok {
2118				return true
2119			}
2120			labels[label.Label.Obj] = label.Stmt
2121			return true
2122		})
2123
2124		ast.Inspect(body, func(node ast.Node) bool {
2125			var loop ast.Node
2126			var body *ast.BlockStmt
2127			switch node := node.(type) {
2128			case *ast.ForStmt:
2129				body = node.Body
2130				loop = node
2131			case *ast.RangeStmt:
2132				typ := pass.TypesInfo.TypeOf(node.X)
2133				if _, ok := typ.Underlying().(*types.Map); ok {
2134					// looping once over a map is a valid pattern for
2135					// getting an arbitrary element.
2136					return true
2137				}
2138				body = node.Body
2139				loop = node
2140			default:
2141				return true
2142			}
2143			if len(body.List) < 2 {
2144				// avoid flagging the somewhat common pattern of using
2145				// a range loop to get the first element in a slice,
2146				// or the first rune in a string.
2147				return true
2148			}
2149			var unconditionalExit ast.Node
2150			hasBranching := false
2151			for _, stmt := range body.List {
2152				switch stmt := stmt.(type) {
2153				case *ast.BranchStmt:
2154					switch stmt.Tok {
2155					case token.BREAK:
2156						if stmt.Label == nil || labels[stmt.Label.Obj] == loop {
2157							unconditionalExit = stmt
2158						}
2159					case token.CONTINUE:
2160						if stmt.Label == nil || labels[stmt.Label.Obj] == loop {
2161							unconditionalExit = nil
2162							return false
2163						}
2164					}
2165				case *ast.ReturnStmt:
2166					unconditionalExit = stmt
2167				case *ast.IfStmt, *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.SelectStmt:
2168					hasBranching = true
2169				}
2170			}
2171			if unconditionalExit == nil || !hasBranching {
2172				return false
2173			}
2174			ast.Inspect(body, func(node ast.Node) bool {
2175				if branch, ok := node.(*ast.BranchStmt); ok {
2176
2177					switch branch.Tok {
2178					case token.GOTO:
2179						unconditionalExit = nil
2180						return false
2181					case token.CONTINUE:
2182						if branch.Label != nil && labels[branch.Label.Obj] != loop {
2183							return true
2184						}
2185						unconditionalExit = nil
2186						return false
2187					}
2188				}
2189				return true
2190			})
2191			if unconditionalExit != nil {
2192				report.Report(pass, unconditionalExit, "the surrounding loop is unconditionally terminated")
2193			}
2194			return true
2195		})
2196	}
2197	code.Preorder(pass, fn, (*ast.FuncDecl)(nil), (*ast.FuncLit)(nil))
2198	return nil, nil
2199}
2200
2201var checkNilContextQ = pattern.MustParse(`(CallExpr fun@(Function _) (Builtin "nil"):_)`)
2202
2203func CheckNilContext(pass *analysis.Pass) (interface{}, error) {
2204	todo := &ast.CallExpr{
2205		Fun: Selector("context", "TODO"),
2206	}
2207	bg := &ast.CallExpr{
2208		Fun: Selector("context", "Background"),
2209	}
2210	fn := func(node ast.Node) {
2211		m, ok := Match(pass, checkNilContextQ, node)
2212		if !ok {
2213			return
2214		}
2215
2216		call := node.(*ast.CallExpr)
2217		fun, ok := m.State["fun"].(*types.Func)
2218		if !ok {
2219			// it might also be a builtin
2220			return
2221		}
2222		sig := fun.Type().(*types.Signature)
2223		if sig.Params().Len() == 0 {
2224			// Our CallExpr might've matched a method expression, like
2225			// (*T).Foo(nil) – here, nil isn't the first argument of
2226			// the Foo method, but the method receiver.
2227			return
2228		}
2229		if !code.IsType(sig.Params().At(0).Type(), "context.Context") {
2230			return
2231		}
2232		report.Report(pass, call.Args[0],
2233			"do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use", report.Fixes(
2234				edit.Fix("use context.TODO", edit.ReplaceWithNode(pass.Fset, call.Args[0], todo)),
2235				edit.Fix("use context.Background", edit.ReplaceWithNode(pass.Fset, call.Args[0], bg))))
2236	}
2237	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
2238	return nil, nil
2239}
2240
2241var (
2242	checkSeekerQ = pattern.MustParse(`(CallExpr fun@(SelectorExpr _ (Ident "Seek")) [arg1@(SelectorExpr (Ident "io") (Ident (Or "SeekStart" "SeekCurrent" "SeekEnd"))) arg2])`)
2243	checkSeekerR = pattern.MustParse(`(CallExpr fun [arg2 arg1])`)
2244)
2245
2246func CheckSeeker(pass *analysis.Pass) (interface{}, error) {
2247	fn := func(node ast.Node) {
2248		if _, edits, ok := MatchAndEdit(pass, checkSeekerQ, checkSeekerR, node); ok {
2249			report.Report(pass, node, "the first argument of io.Seeker is the offset, but an io.Seek* constant is being used instead",
2250				report.Fixes(edit.Fix("swap arguments", edits...)))
2251		}
2252	}
2253	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
2254	return nil, nil
2255}
2256
2257func CheckIneffectiveAppend(pass *analysis.Pass) (interface{}, error) {
2258	isAppend := func(ins ir.Value) bool {
2259		call, ok := ins.(*ir.Call)
2260		if !ok {
2261			return false
2262		}
2263		if call.Call.IsInvoke() {
2264			return false
2265		}
2266		if builtin, ok := call.Call.Value.(*ir.Builtin); !ok || builtin.Name() != "append" {
2267			return false
2268		}
2269		return true
2270	}
2271
2272	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2273		for _, block := range fn.Blocks {
2274			for _, ins := range block.Instrs {
2275				val, ok := ins.(ir.Value)
2276				if !ok || !isAppend(val) {
2277					continue
2278				}
2279
2280				isUsed := false
2281				visited := map[ir.Instruction]bool{}
2282				var walkRefs func(refs []ir.Instruction)
2283				walkRefs = func(refs []ir.Instruction) {
2284				loop:
2285					for _, ref := range refs {
2286						if visited[ref] {
2287							continue
2288						}
2289						visited[ref] = true
2290						if _, ok := ref.(*ir.DebugRef); ok {
2291							continue
2292						}
2293						switch ref := ref.(type) {
2294						case *ir.Phi:
2295							walkRefs(*ref.Referrers())
2296						case *ir.Sigma:
2297							walkRefs(*ref.Referrers())
2298						case ir.Value:
2299							if !isAppend(ref) {
2300								isUsed = true
2301							} else {
2302								walkRefs(*ref.Referrers())
2303							}
2304						case ir.Instruction:
2305							isUsed = true
2306							break loop
2307						}
2308					}
2309				}
2310
2311				refs := val.Referrers()
2312				if refs == nil {
2313					continue
2314				}
2315				walkRefs(*refs)
2316
2317				if !isUsed {
2318					report.Report(pass, ins, "this result of append is never used, except maybe in other appends")
2319				}
2320			}
2321		}
2322	}
2323	return nil, nil
2324}
2325
2326func CheckConcurrentTesting(pass *analysis.Pass) (interface{}, error) {
2327	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2328		for _, block := range fn.Blocks {
2329			for _, ins := range block.Instrs {
2330				gostmt, ok := ins.(*ir.Go)
2331				if !ok {
2332					continue
2333				}
2334				var fn *ir.Function
2335				switch val := gostmt.Call.Value.(type) {
2336				case *ir.Function:
2337					fn = val
2338				case *ir.MakeClosure:
2339					fn = val.Fn.(*ir.Function)
2340				default:
2341					continue
2342				}
2343				if fn.Blocks == nil {
2344					continue
2345				}
2346				for _, block := range fn.Blocks {
2347					for _, ins := range block.Instrs {
2348						call, ok := ins.(*ir.Call)
2349						if !ok {
2350							continue
2351						}
2352						if call.Call.IsInvoke() {
2353							continue
2354						}
2355						callee := call.Call.StaticCallee()
2356						if callee == nil {
2357							continue
2358						}
2359						recv := callee.Signature.Recv()
2360						if recv == nil {
2361							continue
2362						}
2363						if !code.IsType(recv.Type(), "*testing.common") {
2364							continue
2365						}
2366						fn, ok := call.Call.StaticCallee().Object().(*types.Func)
2367						if !ok {
2368							continue
2369						}
2370						name := fn.Name()
2371						switch name {
2372						case "FailNow", "Fatal", "Fatalf", "SkipNow", "Skip", "Skipf":
2373						default:
2374							continue
2375						}
2376						// TODO(dh): don't report multiple diagnostics
2377						// for multiple calls to T.Fatal, but do
2378						// collect all of them as related information
2379						report.Report(pass, gostmt, fmt.Sprintf("the goroutine calls T.%s, which must be called in the same goroutine as the test", name),
2380							report.Related(call, fmt.Sprintf("call to T.%s", name)))
2381					}
2382				}
2383			}
2384		}
2385	}
2386	return nil, nil
2387}
2388
2389func eachCall(fn *ir.Function, cb func(caller *ir.Function, site ir.CallInstruction, callee *ir.Function)) {
2390	for _, b := range fn.Blocks {
2391		for _, instr := range b.Instrs {
2392			if site, ok := instr.(ir.CallInstruction); ok {
2393				if g := site.Common().StaticCallee(); g != nil {
2394					cb(fn, site, g)
2395				}
2396			}
2397		}
2398	}
2399}
2400
2401func CheckCyclicFinalizer(pass *analysis.Pass) (interface{}, error) {
2402	cb := func(caller *ir.Function, site ir.CallInstruction, callee *ir.Function) {
2403		if callee.RelString(nil) != "runtime.SetFinalizer" {
2404			return
2405		}
2406		arg0 := site.Common().Args[Arg("runtime.SetFinalizer.obj")]
2407		if iface, ok := arg0.(*ir.MakeInterface); ok {
2408			arg0 = iface.X
2409		}
2410		load, ok := arg0.(*ir.Load)
2411		if !ok {
2412			return
2413		}
2414		v, ok := load.X.(*ir.Alloc)
2415		if !ok {
2416			return
2417		}
2418		arg1 := site.Common().Args[Arg("runtime.SetFinalizer.finalizer")]
2419		if iface, ok := arg1.(*ir.MakeInterface); ok {
2420			arg1 = iface.X
2421		}
2422		mc, ok := arg1.(*ir.MakeClosure)
2423		if !ok {
2424			return
2425		}
2426		for _, b := range mc.Bindings {
2427			if b == v {
2428				pos := lint.DisplayPosition(pass.Fset, mc.Fn.Pos())
2429				report.Report(pass, site, fmt.Sprintf("the finalizer closes over the object, preventing the finalizer from ever running (at %s)", pos))
2430			}
2431		}
2432	}
2433	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2434		eachCall(fn, cb)
2435	}
2436	return nil, nil
2437}
2438
2439/*
2440func CheckSliceOutOfBounds(pass *analysis.Pass) (interface{}, error) {
2441	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2442		for _, block := range fn.Blocks {
2443			for _, ins := range block.Instrs {
2444				ia, ok := ins.(*ir.IndexAddr)
2445				if !ok {
2446					continue
2447				}
2448				if _, ok := ia.X.Type().Underlying().(*types.Slice); !ok {
2449					continue
2450				}
2451				sr, ok1 := c.funcDescs.Get(fn).Ranges[ia.X].(vrp.SliceInterval)
2452				idxr, ok2 := c.funcDescs.Get(fn).Ranges[ia.Index].(vrp.IntInterval)
2453				if !ok1 || !ok2 || !sr.IsKnown() || !idxr.IsKnown() || sr.Length.Empty() || idxr.Empty() {
2454					continue
2455				}
2456				if idxr.Lower.Cmp(sr.Length.Upper) >= 0 {
2457					report.Nodef(pass, ia, "index out of bounds")
2458				}
2459			}
2460		}
2461	}
2462	return nil, nil
2463}
2464*/
2465
2466func CheckDeferLock(pass *analysis.Pass) (interface{}, error) {
2467	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2468		for _, block := range fn.Blocks {
2469			instrs := code.FilterDebug(block.Instrs)
2470			if len(instrs) < 2 {
2471				continue
2472			}
2473			for i, ins := range instrs[:len(instrs)-1] {
2474				call, ok := ins.(*ir.Call)
2475				if !ok {
2476					continue
2477				}
2478				if !code.IsCallToAny(call.Common(), "(*sync.Mutex).Lock", "(*sync.RWMutex).RLock") {
2479					continue
2480				}
2481				nins, ok := instrs[i+1].(*ir.Defer)
2482				if !ok {
2483					continue
2484				}
2485				if !code.IsCallToAny(&nins.Call, "(*sync.Mutex).Lock", "(*sync.RWMutex).RLock") {
2486					continue
2487				}
2488				if call.Common().Args[0] != nins.Call.Args[0] {
2489					continue
2490				}
2491				name := shortCallName(call.Common())
2492				alt := ""
2493				switch name {
2494				case "Lock":
2495					alt = "Unlock"
2496				case "RLock":
2497					alt = "RUnlock"
2498				}
2499				report.Report(pass, nins, fmt.Sprintf("deferring %s right after having locked already; did you mean to defer %s?", name, alt))
2500			}
2501		}
2502	}
2503	return nil, nil
2504}
2505
2506func CheckNaNComparison(pass *analysis.Pass) (interface{}, error) {
2507	isNaN := func(v ir.Value) bool {
2508		call, ok := v.(*ir.Call)
2509		if !ok {
2510			return false
2511		}
2512		return code.IsCallTo(call.Common(), "math.NaN")
2513	}
2514	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2515		for _, block := range fn.Blocks {
2516			for _, ins := range block.Instrs {
2517				ins, ok := ins.(*ir.BinOp)
2518				if !ok {
2519					continue
2520				}
2521				if isNaN(ins.X) || isNaN(ins.Y) {
2522					report.Report(pass, ins, "no value is equal to NaN, not even NaN itself")
2523				}
2524			}
2525		}
2526	}
2527	return nil, nil
2528}
2529
2530func CheckInfiniteRecursion(pass *analysis.Pass) (interface{}, error) {
2531	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2532		eachCall(fn, func(caller *ir.Function, site ir.CallInstruction, callee *ir.Function) {
2533			if callee != fn {
2534				return
2535			}
2536			if _, ok := site.(*ir.Go); ok {
2537				// Recursively spawning goroutines doesn't consume
2538				// stack space infinitely, so don't flag it.
2539				return
2540			}
2541
2542			block := site.Block()
2543			canReturn := false
2544			for _, b := range fn.Blocks {
2545				if block.Dominates(b) {
2546					continue
2547				}
2548				if len(b.Instrs) == 0 {
2549					continue
2550				}
2551				if _, ok := b.Control().(*ir.Return); ok {
2552					canReturn = true
2553					break
2554				}
2555			}
2556			if canReturn {
2557				return
2558			}
2559			report.Report(pass, site, "infinite recursive call")
2560		})
2561	}
2562	return nil, nil
2563}
2564
2565func objectName(obj types.Object) string {
2566	if obj == nil {
2567		return "<nil>"
2568	}
2569	var name string
2570	if obj.Pkg() != nil && obj.Pkg().Scope().Lookup(obj.Name()) == obj {
2571		s := obj.Pkg().Path()
2572		if s != "" {
2573			name += s + "."
2574		}
2575	}
2576	name += obj.Name()
2577	return name
2578}
2579
2580func isName(pass *analysis.Pass, expr ast.Expr, name string) bool {
2581	var obj types.Object
2582	switch expr := expr.(type) {
2583	case *ast.Ident:
2584		obj = pass.TypesInfo.ObjectOf(expr)
2585	case *ast.SelectorExpr:
2586		obj = pass.TypesInfo.ObjectOf(expr.Sel)
2587	}
2588	return objectName(obj) == name
2589}
2590
2591func CheckLeakyTimeTick(pass *analysis.Pass) (interface{}, error) {
2592	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2593		if code.IsMainLike(pass) || code.IsInTest(pass, fn) {
2594			continue
2595		}
2596		for _, block := range fn.Blocks {
2597			for _, ins := range block.Instrs {
2598				call, ok := ins.(*ir.Call)
2599				if !ok || !code.IsCallTo(call.Common(), "time.Tick") {
2600					continue
2601				}
2602				if !functions.Terminates(call.Parent()) {
2603					continue
2604				}
2605				report.Report(pass, call, "using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here")
2606			}
2607		}
2608	}
2609	return nil, nil
2610}
2611
2612var checkDoubleNegationQ = pattern.MustParse(`(UnaryExpr "!" single@(UnaryExpr "!" x))`)
2613
2614func CheckDoubleNegation(pass *analysis.Pass) (interface{}, error) {
2615	fn := func(node ast.Node) {
2616		if m, ok := Match(pass, checkDoubleNegationQ, node); ok {
2617			report.Report(pass, node, "negating a boolean twice has no effect; is this a typo?", report.Fixes(
2618				edit.Fix("turn into single negation", edit.ReplaceWithNode(pass.Fset, node, m.State["single"].(ast.Node))),
2619				edit.Fix("remove double negation", edit.ReplaceWithNode(pass.Fset, node, m.State["x"].(ast.Node)))))
2620		}
2621	}
2622	code.Preorder(pass, fn, (*ast.UnaryExpr)(nil))
2623	return nil, nil
2624}
2625
2626func CheckRepeatedIfElse(pass *analysis.Pass) (interface{}, error) {
2627	seen := map[ast.Node]bool{}
2628
2629	var collectConds func(ifstmt *ast.IfStmt, conds []ast.Expr) ([]ast.Expr, bool)
2630	collectConds = func(ifstmt *ast.IfStmt, conds []ast.Expr) ([]ast.Expr, bool) {
2631		seen[ifstmt] = true
2632		// Bail if any if-statement has an Init statement or side effects in its condition
2633		if ifstmt.Init != nil {
2634			return nil, false
2635		}
2636		if code.MayHaveSideEffects(pass, ifstmt.Cond, nil) {
2637			return nil, false
2638		}
2639
2640		conds = append(conds, ifstmt.Cond)
2641		if elsestmt, ok := ifstmt.Else.(*ast.IfStmt); ok {
2642			return collectConds(elsestmt, conds)
2643		}
2644		return conds, true
2645	}
2646	fn := func(node ast.Node) {
2647		ifstmt := node.(*ast.IfStmt)
2648		if seen[ifstmt] {
2649			// this if-statement is part of an if/else-if chain that we've already processed
2650			return
2651		}
2652		if ifstmt.Else == nil {
2653			// there can be at most one condition
2654			return
2655		}
2656		conds, ok := collectConds(ifstmt, nil)
2657		if !ok {
2658			return
2659		}
2660		if len(conds) < 2 {
2661			return
2662		}
2663		counts := map[string]int{}
2664		for _, cond := range conds {
2665			s := report.Render(pass, cond)
2666			counts[s]++
2667			if counts[s] == 2 {
2668				report.Report(pass, cond, "this condition occurs multiple times in this if/else if chain")
2669			}
2670		}
2671	}
2672	code.Preorder(pass, fn, (*ast.IfStmt)(nil))
2673	return nil, nil
2674}
2675
2676func CheckSillyBitwiseOps(pass *analysis.Pass) (interface{}, error) {
2677	// FIXME(dh): what happened here?
2678	if false {
2679		for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2680			for _, block := range fn.Blocks {
2681				for _, ins := range block.Instrs {
2682					ins, ok := ins.(*ir.BinOp)
2683					if !ok {
2684						continue
2685					}
2686
2687					if c, ok := ins.Y.(*ir.Const); !ok || c.Value == nil || c.Value.Kind() != constant.Int || c.Uint64() != 0 {
2688						continue
2689					}
2690					switch ins.Op {
2691					case token.AND, token.OR, token.XOR:
2692					default:
2693						// we do not flag shifts because too often, x<<0 is part
2694						// of a pattern, x<<0, x<<8, x<<16, ...
2695						continue
2696					}
2697					path, _ := astutil.PathEnclosingInterval(code.File(pass, ins), ins.Pos(), ins.Pos())
2698					if len(path) == 0 {
2699						continue
2700					}
2701
2702					if node, ok := path[0].(*ast.BinaryExpr); !ok || !code.IsIntLiteral(node.Y, "0") {
2703						continue
2704					}
2705
2706					switch ins.Op {
2707					case token.AND:
2708						report.Report(pass, ins, "x & 0 always equals 0")
2709					case token.OR, token.XOR:
2710						report.Report(pass, ins, fmt.Sprintf("x %s 0 always equals x", ins.Op))
2711					}
2712				}
2713			}
2714		}
2715	}
2716	fn := func(node ast.Node) {
2717		binop := node.(*ast.BinaryExpr)
2718		b, ok := pass.TypesInfo.TypeOf(binop).Underlying().(*types.Basic)
2719		if !ok {
2720			return
2721		}
2722		if (b.Info() & types.IsInteger) == 0 {
2723			return
2724		}
2725		switch binop.Op {
2726		case token.AND, token.OR, token.XOR:
2727		default:
2728			// we do not flag shifts because too often, x<<0 is part
2729			// of a pattern, x<<0, x<<8, x<<16, ...
2730			return
2731		}
2732		switch y := binop.Y.(type) {
2733		case *ast.Ident:
2734			obj, ok := pass.TypesInfo.ObjectOf(y).(*types.Const)
2735			if !ok {
2736				return
2737			}
2738			if obj.Pkg() != pass.Pkg {
2739				// identifier was dot-imported
2740				return
2741			}
2742			if v, _ := constant.Int64Val(obj.Val()); v != 0 {
2743				return
2744			}
2745			path, _ := astutil.PathEnclosingInterval(code.File(pass, obj), obj.Pos(), obj.Pos())
2746			if len(path) < 2 {
2747				return
2748			}
2749			spec, ok := path[1].(*ast.ValueSpec)
2750			if !ok {
2751				return
2752			}
2753			if len(spec.Names) != 1 || len(spec.Values) != 1 {
2754				// TODO(dh): we could support this
2755				return
2756			}
2757			ident, ok := spec.Values[0].(*ast.Ident)
2758			if !ok {
2759				return
2760			}
2761			if !isIota(pass.TypesInfo.ObjectOf(ident)) {
2762				return
2763			}
2764			switch binop.Op {
2765			case token.AND:
2766				report.Report(pass, node,
2767					fmt.Sprintf("%s always equals 0; %s is defined as iota and has value 0, maybe %s is meant to be 1 << iota?", report.Render(pass, binop), report.Render(pass, binop.Y), report.Render(pass, binop.Y)))
2768			case token.OR, token.XOR:
2769				report.Report(pass, node,
2770					fmt.Sprintf("%s always equals %s; %s is defined as iota and has value 0, maybe %s is meant to be 1 << iota?", report.Render(pass, binop), report.Render(pass, binop.X), report.Render(pass, binop.Y), report.Render(pass, binop.Y)))
2771			}
2772		case *ast.BasicLit:
2773			if !code.IsIntLiteral(binop.Y, "0") {
2774				return
2775			}
2776			switch binop.Op {
2777			case token.AND:
2778				report.Report(pass, node, fmt.Sprintf("%s always equals 0", report.Render(pass, binop)))
2779			case token.OR, token.XOR:
2780				report.Report(pass, node, fmt.Sprintf("%s always equals %s", report.Render(pass, binop), report.Render(pass, binop.X)))
2781			}
2782		default:
2783			return
2784		}
2785	}
2786	code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
2787	return nil, nil
2788}
2789
2790func isIota(obj types.Object) bool {
2791	if obj.Name() != "iota" {
2792		return false
2793	}
2794	c, ok := obj.(*types.Const)
2795	if !ok {
2796		return false
2797	}
2798	return c.Pkg() == nil
2799}
2800
2801func CheckNonOctalFileMode(pass *analysis.Pass) (interface{}, error) {
2802	fn := func(node ast.Node) {
2803		call := node.(*ast.CallExpr)
2804		sig, ok := pass.TypesInfo.TypeOf(call.Fun).(*types.Signature)
2805		if !ok {
2806			return
2807		}
2808		n := sig.Params().Len()
2809		for i := 0; i < n; i++ {
2810			typ := sig.Params().At(i).Type()
2811			if !code.IsType(typ, "os.FileMode") {
2812				continue
2813			}
2814
2815			lit, ok := call.Args[i].(*ast.BasicLit)
2816			if !ok {
2817				continue
2818			}
2819			if len(lit.Value) == 3 &&
2820				lit.Value[0] != '0' &&
2821				lit.Value[0] >= '0' && lit.Value[0] <= '7' &&
2822				lit.Value[1] >= '0' && lit.Value[1] <= '7' &&
2823				lit.Value[2] >= '0' && lit.Value[2] <= '7' {
2824
2825				v, err := strconv.ParseInt(lit.Value, 10, 64)
2826				if err != nil {
2827					continue
2828				}
2829				report.Report(pass, call.Args[i], fmt.Sprintf("file mode '%s' evaluates to %#o; did you mean '0%s'?", lit.Value, v, lit.Value),
2830					report.Fixes(edit.Fix("fix octal literal", edit.ReplaceWithString(pass.Fset, call.Args[i], "0"+lit.Value))))
2831			}
2832		}
2833	}
2834	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
2835	return nil, nil
2836}
2837
2838func CheckPureFunctions(pass *analysis.Pass) (interface{}, error) {
2839	pure := pass.ResultOf[facts.Purity].(facts.PurityResult)
2840
2841fnLoop:
2842	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
2843		if code.IsInTest(pass, fn) {
2844			params := fn.Signature.Params()
2845			for i := 0; i < params.Len(); i++ {
2846				param := params.At(i)
2847				if code.IsType(param.Type(), "*testing.B") {
2848					// Ignore discarded pure functions in code related
2849					// to benchmarks. Instead of matching BenchmarkFoo
2850					// functions, we match any function accepting a
2851					// *testing.B. Benchmarks sometimes call generic
2852					// functions for doing the actual work, and
2853					// checking for the parameter is a lot easier and
2854					// faster than analyzing call trees.
2855					continue fnLoop
2856				}
2857			}
2858		}
2859
2860		for _, b := range fn.Blocks {
2861			for _, ins := range b.Instrs {
2862				ins, ok := ins.(*ir.Call)
2863				if !ok {
2864					continue
2865				}
2866				refs := ins.Referrers()
2867				if refs == nil || len(code.FilterDebug(*refs)) > 0 {
2868					continue
2869				}
2870
2871				callee := ins.Common().StaticCallee()
2872				if callee == nil {
2873					continue
2874				}
2875				if callee.Object() == nil {
2876					// TODO(dh): support anonymous functions
2877					continue
2878				}
2879				if _, ok := pure[callee.Object().(*types.Func)]; ok {
2880					if pass.Pkg.Path() == "fmt_test" && callee.Object().(*types.Func).FullName() == "fmt.Sprintf" {
2881						// special case for benchmarks in the fmt package
2882						continue
2883					}
2884					report.Report(pass, ins, fmt.Sprintf("%s is a pure function but its return value is ignored", callee.Name()))
2885				}
2886			}
2887		}
2888	}
2889	return nil, nil
2890}
2891
2892func CheckDeprecated(pass *analysis.Pass) (interface{}, error) {
2893	deprs := pass.ResultOf[facts.Deprecated].(facts.DeprecatedResult)
2894
2895	// Selectors can appear outside of function literals, e.g. when
2896	// declaring package level variables.
2897
2898	var tfn types.Object
2899	stack := 0
2900	fn := func(node ast.Node, push bool) bool {
2901		if !push {
2902			stack--
2903			return false
2904		}
2905		stack++
2906		if stack == 1 {
2907			tfn = nil
2908		}
2909		if fn, ok := node.(*ast.FuncDecl); ok {
2910			tfn = pass.TypesInfo.ObjectOf(fn.Name)
2911		}
2912		sel, ok := node.(*ast.SelectorExpr)
2913		if !ok {
2914			return true
2915		}
2916
2917		obj := pass.TypesInfo.ObjectOf(sel.Sel)
2918		if obj.Pkg() == nil {
2919			return true
2920		}
2921		if pass.Pkg == obj.Pkg() || obj.Pkg().Path()+"_test" == pass.Pkg.Path() {
2922			// Don't flag stuff in our own package
2923			return true
2924		}
2925		if depr, ok := deprs.Objects[obj]; ok {
2926			// Look for the first available alternative, not the first
2927			// version something was deprecated in. If a function was
2928			// deprecated in Go 1.6, an alternative has been available
2929			// already in 1.0, and we're targeting 1.2, it still
2930			// makes sense to use the alternative from 1.0, to be
2931			// future-proof.
2932			minVersion := deprecated.Stdlib[code.SelectorName(pass, sel)].AlternativeAvailableSince
2933			if !code.IsGoVersion(pass, minVersion) {
2934				return true
2935			}
2936
2937			if tfn != nil {
2938				if _, ok := deprs.Objects[tfn]; ok {
2939					// functions that are deprecated may use deprecated
2940					// symbols
2941					return true
2942				}
2943			}
2944			report.Report(pass, sel, fmt.Sprintf("%s is deprecated: %s", report.Render(pass, sel), depr.Msg))
2945			return true
2946		}
2947		return true
2948	}
2949
2950	fn2 := func(node ast.Node) {
2951		spec := node.(*ast.ImportSpec)
2952		var imp *types.Package
2953		if spec.Name != nil {
2954			imp = pass.TypesInfo.ObjectOf(spec.Name).(*types.PkgName).Imported()
2955		} else {
2956			imp = pass.TypesInfo.Implicits[spec].(*types.PkgName).Imported()
2957		}
2958
2959		p := spec.Path.Value
2960		path := p[1 : len(p)-1]
2961		if depr, ok := deprs.Packages[imp]; ok {
2962			if path == "github.com/golang/protobuf/proto" {
2963				gen, ok := code.Generator(pass, spec.Path.Pos())
2964				if ok && gen == facts.ProtocGenGo {
2965					return
2966				}
2967			}
2968			report.Report(pass, spec, fmt.Sprintf("package %s is deprecated: %s", path, depr.Msg))
2969		}
2970	}
2971	pass.ResultOf[inspect.Analyzer].(*inspector.Inspector).Nodes(nil, fn)
2972	code.Preorder(pass, fn2, (*ast.ImportSpec)(nil))
2973	return nil, nil
2974}
2975
2976func callChecker(rules map[string]CallCheck) func(pass *analysis.Pass) (interface{}, error) {
2977	return func(pass *analysis.Pass) (interface{}, error) {
2978		return checkCalls(pass, rules)
2979	}
2980}
2981
2982func checkCalls(pass *analysis.Pass, rules map[string]CallCheck) (interface{}, error) {
2983	cb := func(caller *ir.Function, site ir.CallInstruction, callee *ir.Function) {
2984		obj, ok := callee.Object().(*types.Func)
2985		if !ok {
2986			return
2987		}
2988
2989		r, ok := rules[lint.FuncName(obj)]
2990		if !ok {
2991			return
2992		}
2993		var args []*Argument
2994		irargs := site.Common().Args
2995		if callee.Signature.Recv() != nil {
2996			irargs = irargs[1:]
2997		}
2998		for _, arg := range irargs {
2999			if iarg, ok := arg.(*ir.MakeInterface); ok {
3000				arg = iarg.X
3001			}
3002			args = append(args, &Argument{Value: Value{arg}})
3003		}
3004		call := &Call{
3005			Pass:   pass,
3006			Instr:  site,
3007			Args:   args,
3008			Parent: site.Parent(),
3009		}
3010		r(call)
3011		path, _ := astutil.PathEnclosingInterval(code.File(pass, site), site.Pos(), site.Pos())
3012		var astcall *ast.CallExpr
3013		for _, el := range path {
3014			if expr, ok := el.(*ast.CallExpr); ok {
3015				astcall = expr
3016				break
3017			}
3018		}
3019		for idx, arg := range call.Args {
3020			for _, e := range arg.invalids {
3021				if astcall != nil {
3022					report.Report(pass, astcall.Args[idx], e)
3023				} else {
3024					report.Report(pass, site, e)
3025				}
3026			}
3027		}
3028		for _, e := range call.invalids {
3029			report.Report(pass, call.Instr, e)
3030		}
3031	}
3032	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3033		eachCall(fn, cb)
3034	}
3035	return nil, nil
3036}
3037
3038func shortCallName(call *ir.CallCommon) string {
3039	if call.IsInvoke() {
3040		return ""
3041	}
3042	switch v := call.Value.(type) {
3043	case *ir.Function:
3044		fn, ok := v.Object().(*types.Func)
3045		if !ok {
3046			return ""
3047		}
3048		return fn.Name()
3049	case *ir.Builtin:
3050		return v.Name()
3051	}
3052	return ""
3053}
3054
3055func CheckWriterBufferModified(pass *analysis.Pass) (interface{}, error) {
3056	// TODO(dh): this might be a good candidate for taint analysis.
3057	// Taint the argument as MUST_NOT_MODIFY, then propagate that
3058	// through functions like bytes.Split
3059
3060	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3061		sig := fn.Signature
3062		if fn.Name() != "Write" || sig.Recv() == nil || sig.Params().Len() != 1 || sig.Results().Len() != 2 {
3063			continue
3064		}
3065		tArg, ok := sig.Params().At(0).Type().(*types.Slice)
3066		if !ok {
3067			continue
3068		}
3069		if basic, ok := tArg.Elem().(*types.Basic); !ok || basic.Kind() != types.Byte {
3070			continue
3071		}
3072		if basic, ok := sig.Results().At(0).Type().(*types.Basic); !ok || basic.Kind() != types.Int {
3073			continue
3074		}
3075		if named, ok := sig.Results().At(1).Type().(*types.Named); !ok || !code.IsType(named, "error") {
3076			continue
3077		}
3078
3079		for _, block := range fn.Blocks {
3080			for _, ins := range block.Instrs {
3081				switch ins := ins.(type) {
3082				case *ir.Store:
3083					addr, ok := ins.Addr.(*ir.IndexAddr)
3084					if !ok {
3085						continue
3086					}
3087					if addr.X != fn.Params[1] {
3088						continue
3089					}
3090					report.Report(pass, ins, "io.Writer.Write must not modify the provided buffer, not even temporarily")
3091				case *ir.Call:
3092					if !code.IsCallTo(ins.Common(), "append") {
3093						continue
3094					}
3095					if ins.Common().Args[0] != fn.Params[1] {
3096						continue
3097					}
3098					report.Report(pass, ins, "io.Writer.Write must not modify the provided buffer, not even temporarily")
3099				}
3100			}
3101		}
3102	}
3103	return nil, nil
3104}
3105
3106func loopedRegexp(name string) CallCheck {
3107	return func(call *Call) {
3108		if len(extractConsts(call.Args[0].Value.Value)) == 0 {
3109			return
3110		}
3111		if !isInLoop(call.Instr.Block()) {
3112			return
3113		}
3114		call.Invalid(fmt.Sprintf("calling %s in a loop has poor performance, consider using regexp.Compile", name))
3115	}
3116}
3117
3118func CheckEmptyBranch(pass *analysis.Pass) (interface{}, error) {
3119	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3120		if fn.Source() == nil {
3121			continue
3122		}
3123		if code.IsExample(fn) {
3124			continue
3125		}
3126		cb := func(node ast.Node) bool {
3127			ifstmt, ok := node.(*ast.IfStmt)
3128			if !ok {
3129				return true
3130			}
3131			if ifstmt.Else != nil {
3132				b, ok := ifstmt.Else.(*ast.BlockStmt)
3133				if !ok || len(b.List) != 0 {
3134					return true
3135				}
3136				report.Report(pass, ifstmt.Else, "empty branch", report.FilterGenerated(), report.ShortRange())
3137			}
3138			if len(ifstmt.Body.List) != 0 {
3139				return true
3140			}
3141			report.Report(pass, ifstmt, "empty branch", report.FilterGenerated(), report.ShortRange())
3142			return true
3143		}
3144		Inspect(fn.Source(), cb)
3145	}
3146	return nil, nil
3147}
3148
3149func CheckMapBytesKey(pass *analysis.Pass) (interface{}, error) {
3150	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3151		for _, b := range fn.Blocks {
3152		insLoop:
3153			for _, ins := range b.Instrs {
3154				// find []byte -> string conversions
3155				conv, ok := ins.(*ir.Convert)
3156				if !ok || conv.Type() != types.Universe.Lookup("string").Type() {
3157					continue
3158				}
3159				if s, ok := conv.X.Type().(*types.Slice); !ok || s.Elem() != types.Universe.Lookup("byte").Type() {
3160					continue
3161				}
3162				refs := conv.Referrers()
3163				// need at least two (DebugRef) references: the
3164				// conversion and the *ast.Ident
3165				if refs == nil || len(*refs) < 2 {
3166					continue
3167				}
3168				ident := false
3169				// skip first reference, that's the conversion itself
3170				for _, ref := range (*refs)[1:] {
3171					switch ref := ref.(type) {
3172					case *ir.DebugRef:
3173						if _, ok := ref.Expr.(*ast.Ident); !ok {
3174							// the string seems to be used somewhere
3175							// unexpected; the default branch should
3176							// catch this already, but be safe
3177							continue insLoop
3178						} else {
3179							ident = true
3180						}
3181					case *ir.MapLookup:
3182					default:
3183						// the string is used somewhere else than a
3184						// map lookup
3185						continue insLoop
3186					}
3187				}
3188
3189				// the result of the conversion wasn't assigned to an
3190				// identifier
3191				if !ident {
3192					continue
3193				}
3194				report.Report(pass, conv, "m[string(key)] would be more efficient than k := string(key); m[k]")
3195			}
3196		}
3197	}
3198	return nil, nil
3199}
3200
3201func CheckRangeStringRunes(pass *analysis.Pass) (interface{}, error) {
3202	return sharedcheck.CheckRangeStringRunes(pass)
3203}
3204
3205func CheckSelfAssignment(pass *analysis.Pass) (interface{}, error) {
3206	pure := pass.ResultOf[facts.Purity].(facts.PurityResult)
3207
3208	fn := func(node ast.Node) {
3209		assign := node.(*ast.AssignStmt)
3210		if assign.Tok != token.ASSIGN || len(assign.Lhs) != len(assign.Rhs) {
3211			return
3212		}
3213		for i, lhs := range assign.Lhs {
3214			rhs := assign.Rhs[i]
3215			if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) {
3216				continue
3217			}
3218			if code.MayHaveSideEffects(pass, lhs, pure) || code.MayHaveSideEffects(pass, rhs, pure) {
3219				continue
3220			}
3221
3222			rlh := report.Render(pass, lhs)
3223			rrh := report.Render(pass, rhs)
3224			if rlh == rrh {
3225				report.Report(pass, assign, fmt.Sprintf("self-assignment of %s to %s", rrh, rlh), report.FilterGenerated())
3226			}
3227		}
3228	}
3229	code.Preorder(pass, fn, (*ast.AssignStmt)(nil))
3230	return nil, nil
3231}
3232
3233func buildTagsIdentical(s1, s2 []string) bool {
3234	if len(s1) != len(s2) {
3235		return false
3236	}
3237	s1s := make([]string, len(s1))
3238	copy(s1s, s1)
3239	sort.Strings(s1s)
3240	s2s := make([]string, len(s2))
3241	copy(s2s, s2)
3242	sort.Strings(s2s)
3243	for i, s := range s1s {
3244		if s != s2s[i] {
3245			return false
3246		}
3247	}
3248	return true
3249}
3250
3251func CheckDuplicateBuildConstraints(pass *analysis.Pass) (interface{}, error) {
3252	for _, f := range pass.Files {
3253		constraints := buildTags(f)
3254		for i, constraint1 := range constraints {
3255			for j, constraint2 := range constraints {
3256				if i >= j {
3257					continue
3258				}
3259				if buildTagsIdentical(constraint1, constraint2) {
3260					msg := fmt.Sprintf("identical build constraints %q and %q",
3261						strings.Join(constraint1, " "),
3262						strings.Join(constraint2, " "))
3263					report.Report(pass, f, msg, report.FilterGenerated(), report.ShortRange())
3264				}
3265			}
3266		}
3267	}
3268	return nil, nil
3269}
3270
3271func CheckSillyRegexp(pass *analysis.Pass) (interface{}, error) {
3272	// We could use the rule checking engine for this, but the
3273	// arguments aren't really invalid.
3274	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3275		for _, b := range fn.Blocks {
3276			for _, ins := range b.Instrs {
3277				call, ok := ins.(*ir.Call)
3278				if !ok {
3279					continue
3280				}
3281				if !code.IsCallToAny(call.Common(), "regexp.MustCompile", "regexp.Compile", "regexp.Match", "regexp.MatchReader", "regexp.MatchString") {
3282					continue
3283				}
3284				c, ok := call.Common().Args[0].(*ir.Const)
3285				if !ok {
3286					continue
3287				}
3288				s := constant.StringVal(c.Value)
3289				re, err := syntax.Parse(s, 0)
3290				if err != nil {
3291					continue
3292				}
3293				if re.Op != syntax.OpLiteral && re.Op != syntax.OpEmptyMatch {
3294					continue
3295				}
3296				report.Report(pass, call, "regular expression does not contain any meta characters")
3297			}
3298		}
3299	}
3300	return nil, nil
3301}
3302
3303func CheckMissingEnumTypesInDeclaration(pass *analysis.Pass) (interface{}, error) {
3304	fn := func(node ast.Node) {
3305		decl := node.(*ast.GenDecl)
3306		if !decl.Lparen.IsValid() {
3307			return
3308		}
3309		if decl.Tok != token.CONST {
3310			return
3311		}
3312
3313		groups := code.GroupSpecs(pass.Fset, decl.Specs)
3314	groupLoop:
3315		for _, group := range groups {
3316			if len(group) < 2 {
3317				continue
3318			}
3319			if group[0].(*ast.ValueSpec).Type == nil {
3320				// first constant doesn't have a type
3321				continue groupLoop
3322			}
3323			for i, spec := range group {
3324				spec := spec.(*ast.ValueSpec)
3325				if len(spec.Names) != 1 || len(spec.Values) != 1 {
3326					continue groupLoop
3327				}
3328				switch v := spec.Values[0].(type) {
3329				case *ast.BasicLit:
3330				case *ast.UnaryExpr:
3331					if _, ok := v.X.(*ast.BasicLit); !ok {
3332						continue groupLoop
3333					}
3334				default:
3335					// if it's not a literal it might be typed, such as
3336					// time.Microsecond = 1000 * Nanosecond
3337					continue groupLoop
3338				}
3339				if i == 0 {
3340					continue
3341				}
3342				if spec.Type != nil {
3343					continue groupLoop
3344				}
3345			}
3346			var edits []analysis.TextEdit
3347			typ := group[0].(*ast.ValueSpec).Type
3348			for _, spec := range group[1:] {
3349				nspec := *spec.(*ast.ValueSpec)
3350				nspec.Type = typ
3351				edits = append(edits, edit.ReplaceWithNode(pass.Fset, spec, &nspec))
3352			}
3353			report.Report(pass, group[0], "only the first constant in this group has an explicit type", report.Fixes(edit.Fix("add type to all constants in group", edits...)))
3354		}
3355	}
3356	code.Preorder(pass, fn, (*ast.GenDecl)(nil))
3357	return nil, nil
3358}
3359
3360func CheckTimerResetReturnValue(pass *analysis.Pass) (interface{}, error) {
3361	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3362		for _, block := range fn.Blocks {
3363			for _, ins := range block.Instrs {
3364				call, ok := ins.(*ir.Call)
3365				if !ok {
3366					continue
3367				}
3368				if !code.IsCallTo(call.Common(), "(*time.Timer).Reset") {
3369					continue
3370				}
3371				refs := call.Referrers()
3372				if refs == nil {
3373					continue
3374				}
3375				for _, ref := range code.FilterDebug(*refs) {
3376					ifstmt, ok := ref.(*ir.If)
3377					if !ok {
3378						continue
3379					}
3380
3381					found := false
3382					for _, succ := range ifstmt.Block().Succs {
3383						if len(succ.Preds) != 1 {
3384							// Merge point, not a branch in the
3385							// syntactical sense.
3386
3387							// FIXME(dh): this is broken for if
3388							// statements a la "if x || y"
3389							continue
3390						}
3391						irutil.Walk(succ, func(b *ir.BasicBlock) bool {
3392							if !succ.Dominates(b) {
3393								// We've reached the end of the branch
3394								return false
3395							}
3396							for _, ins := range b.Instrs {
3397								// TODO(dh): we should check that
3398								// we're receiving from the channel of
3399								// a time.Timer to further reduce
3400								// false positives. Not a key
3401								// priority, considering the rarity of
3402								// Reset and the tiny likeliness of a
3403								// false positive
3404								if ins, ok := ins.(*ir.Recv); ok && code.IsType(ins.Chan.Type(), "<-chan time.Time") {
3405									found = true
3406									return false
3407								}
3408							}
3409							return true
3410						})
3411					}
3412
3413					if found {
3414						report.Report(pass, call, "it is not possible to use Reset's return value correctly, as there is a race condition between draining the channel and the new timer expiring")
3415					}
3416				}
3417			}
3418		}
3419	}
3420	return nil, nil
3421}
3422
3423var (
3424	checkToLowerToUpperComparisonQ = pattern.MustParse(`
3425	(BinaryExpr
3426		(CallExpr fun@(Function (Or "strings.ToLower" "strings.ToUpper")) [a])
3427 		tok@(Or "==" "!=")
3428 		(CallExpr fun [b]))`)
3429	checkToLowerToUpperComparisonR = pattern.MustParse(`(CallExpr (SelectorExpr (Ident "strings") (Ident "EqualFold")) [a b])`)
3430)
3431
3432func CheckToLowerToUpperComparison(pass *analysis.Pass) (interface{}, error) {
3433	fn := func(node ast.Node) {
3434		m, ok := Match(pass, checkToLowerToUpperComparisonQ, node)
3435		if !ok {
3436			return
3437		}
3438		rn := pattern.NodeToAST(checkToLowerToUpperComparisonR.Root, m.State).(ast.Expr)
3439		if m.State["tok"].(token.Token) == token.NEQ {
3440			rn = &ast.UnaryExpr{
3441				Op: token.NOT,
3442				X:  rn,
3443			}
3444		}
3445
3446		report.Report(pass, node, "should use strings.EqualFold instead", report.Fixes(edit.Fix("replace with strings.EqualFold", edit.ReplaceWithNode(pass.Fset, node, rn))))
3447	}
3448
3449	code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
3450	return nil, nil
3451}
3452
3453func CheckUnreachableTypeCases(pass *analysis.Pass) (interface{}, error) {
3454	// Check if T subsumes V in a type switch. T subsumes V if T is an interface and T's method set is a subset of V's method set.
3455	subsumes := func(T, V types.Type) bool {
3456		tIface, ok := T.Underlying().(*types.Interface)
3457		if !ok {
3458			return false
3459		}
3460
3461		return types.Implements(V, tIface)
3462	}
3463
3464	subsumesAny := func(Ts, Vs []types.Type) (types.Type, types.Type, bool) {
3465		for _, T := range Ts {
3466			for _, V := range Vs {
3467				if subsumes(T, V) {
3468					return T, V, true
3469				}
3470			}
3471		}
3472
3473		return nil, nil, false
3474	}
3475
3476	fn := func(node ast.Node) {
3477		tsStmt := node.(*ast.TypeSwitchStmt)
3478
3479		type ccAndTypes struct {
3480			cc    *ast.CaseClause
3481			types []types.Type
3482		}
3483
3484		// All asserted types in the order of case clauses.
3485		ccs := make([]ccAndTypes, 0, len(tsStmt.Body.List))
3486		for _, stmt := range tsStmt.Body.List {
3487			cc, _ := stmt.(*ast.CaseClause)
3488
3489			// Exclude the 'default' case.
3490			if len(cc.List) == 0 {
3491				continue
3492			}
3493
3494			Ts := make([]types.Type, len(cc.List))
3495			for i, expr := range cc.List {
3496				Ts[i] = pass.TypesInfo.TypeOf(expr)
3497			}
3498
3499			ccs = append(ccs, ccAndTypes{cc: cc, types: Ts})
3500		}
3501
3502		if len(ccs) <= 1 {
3503			// Zero or one case clauses, nothing to check.
3504			return
3505		}
3506
3507		// Check if case clauses following cc have types that are subsumed by cc.
3508		for i, cc := range ccs[:len(ccs)-1] {
3509			for _, next := range ccs[i+1:] {
3510				if T, V, yes := subsumesAny(cc.types, next.types); yes {
3511					report.Report(pass, next.cc, fmt.Sprintf("unreachable case clause: %s will always match before %s", T.String(), V.String()),
3512						report.ShortRange())
3513				}
3514			}
3515		}
3516	}
3517
3518	code.Preorder(pass, fn, (*ast.TypeSwitchStmt)(nil))
3519	return nil, nil
3520}
3521
3522var checkSingleArgAppendQ = pattern.MustParse(`(CallExpr (Builtin "append") [_])`)
3523
3524func CheckSingleArgAppend(pass *analysis.Pass) (interface{}, error) {
3525	fn := func(node ast.Node) {
3526		_, ok := Match(pass, checkSingleArgAppendQ, node)
3527		if !ok {
3528			return
3529		}
3530		report.Report(pass, node, "x = append(y) is equivalent to x = y", report.FilterGenerated())
3531	}
3532	code.Preorder(pass, fn, (*ast.CallExpr)(nil))
3533	return nil, nil
3534}
3535
3536func CheckStructTags(pass *analysis.Pass) (interface{}, error) {
3537	importsGoFlags := false
3538
3539	// we use the AST instead of (*types.Package).Imports to work
3540	// around vendored packages in GOPATH mode. A vendored package's
3541	// path will include the vendoring subtree as a prefix.
3542	for _, f := range pass.Files {
3543		for _, imp := range f.Imports {
3544			v := imp.Path.Value
3545			if v[1:len(v)-1] == "github.com/jessevdk/go-flags" {
3546				importsGoFlags = true
3547				break
3548			}
3549		}
3550	}
3551
3552	fn := func(node ast.Node) {
3553		for _, field := range node.(*ast.StructType).Fields.List {
3554			if field.Tag == nil {
3555				continue
3556			}
3557			tags, err := parseStructTag(field.Tag.Value[1 : len(field.Tag.Value)-1])
3558			if err != nil {
3559				report.Report(pass, field.Tag, fmt.Sprintf("unparseable struct tag: %s", err))
3560				continue
3561			}
3562			for k, v := range tags {
3563				if len(v) > 1 {
3564					isGoFlagsTag := importsGoFlags &&
3565						(k == "choice" || k == "optional-value" || k == "default")
3566					if !isGoFlagsTag {
3567						report.Report(pass, field.Tag, fmt.Sprintf("duplicate struct tag %q", k))
3568					}
3569				}
3570
3571				switch k {
3572				case "json":
3573					checkJSONTag(pass, field, v[0])
3574				case "xml":
3575					checkXMLTag(pass, field, v[0])
3576				}
3577			}
3578		}
3579	}
3580	code.Preorder(pass, fn, (*ast.StructType)(nil))
3581	return nil, nil
3582}
3583
3584func checkJSONTag(pass *analysis.Pass, field *ast.Field, tag string) {
3585	if pass.Pkg.Path() == "encoding/json" || pass.Pkg.Path() == "encoding/json_test" {
3586		// don't flag malformed JSON tags in the encoding/json
3587		// package; it knows what it is doing, and it is testing
3588		// itself.
3589		return
3590	}
3591	//lint:ignore SA9003 TODO(dh): should we flag empty tags?
3592	if len(tag) == 0 {
3593	}
3594	fields := strings.Split(tag, ",")
3595	for _, r := range fields[0] {
3596		if !unicode.IsLetter(r) && !unicode.IsDigit(r) && !strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", r) {
3597			report.Report(pass, field.Tag, fmt.Sprintf("invalid JSON field name %q", fields[0]))
3598		}
3599	}
3600	var co, cs, ci int
3601	for _, s := range fields[1:] {
3602		switch s {
3603		case "omitempty":
3604			co++
3605		case "":
3606			// allow stuff like "-,"
3607		case "string":
3608			cs++
3609			// only for string, floating point, integer and bool
3610			T := code.Dereference(pass.TypesInfo.TypeOf(field.Type).Underlying()).Underlying()
3611			basic, ok := T.(*types.Basic)
3612			if !ok || (basic.Info()&(types.IsBoolean|types.IsInteger|types.IsFloat|types.IsString)) == 0 {
3613				report.Report(pass, field.Tag, "the JSON string option only applies to fields of type string, floating point, integer or bool, or pointers to those")
3614			}
3615		case "inline":
3616			ci++
3617		default:
3618			report.Report(pass, field.Tag, fmt.Sprintf("unknown JSON option %q", s))
3619		}
3620	}
3621	if co > 1 {
3622		report.Report(pass, field.Tag, `duplicate JSON option "omitempty"`)
3623	}
3624	if cs > 1 {
3625		report.Report(pass, field.Tag, `duplicate JSON option "string"`)
3626	}
3627	if ci > 1 {
3628		report.Report(pass, field.Tag, `duplicate JSON option "inline"`)
3629	}
3630}
3631
3632func checkXMLTag(pass *analysis.Pass, field *ast.Field, tag string) {
3633	//lint:ignore SA9003 TODO(dh): should we flag empty tags?
3634	if len(tag) == 0 {
3635	}
3636	fields := strings.Split(tag, ",")
3637	counts := map[string]int{}
3638	var exclusives []string
3639	for _, s := range fields[1:] {
3640		switch s {
3641		case "attr", "chardata", "cdata", "innerxml", "comment":
3642			counts[s]++
3643			if counts[s] == 1 {
3644				exclusives = append(exclusives, s)
3645			}
3646		case "omitempty", "any":
3647			counts[s]++
3648		case "":
3649		default:
3650			report.Report(pass, field.Tag, fmt.Sprintf("unknown XML option %q", s))
3651		}
3652	}
3653	for k, v := range counts {
3654		if v > 1 {
3655			report.Report(pass, field.Tag, fmt.Sprintf("duplicate XML option %q", k))
3656		}
3657	}
3658	if len(exclusives) > 1 {
3659		report.Report(pass, field.Tag, fmt.Sprintf("XML options %s are mutually exclusive", strings.Join(exclusives, " and ")))
3660	}
3661}
3662
3663func CheckImpossibleTypeAssertion(pass *analysis.Pass) (interface{}, error) {
3664	type entry struct {
3665		l, r *types.Func
3666	}
3667
3668	msc := &pass.ResultOf[buildir.Analyzer].(*buildir.IR).Pkg.Prog.MethodSets
3669	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3670		for _, b := range fn.Blocks {
3671			for _, instr := range b.Instrs {
3672				assert, ok := instr.(*ir.TypeAssert)
3673				if !ok {
3674					continue
3675				}
3676				var wrong []entry
3677				left := assert.X.Type()
3678				right := assert.AssertedType
3679				righti, ok := right.Underlying().(*types.Interface)
3680
3681				if !ok {
3682					// We only care about interface->interface
3683					// assertions. The Go compiler already catches
3684					// impossible interface->concrete assertions.
3685					continue
3686				}
3687
3688				ms := msc.MethodSet(left)
3689				for i := 0; i < righti.NumMethods(); i++ {
3690					mr := righti.Method(i)
3691					sel := ms.Lookup(mr.Pkg(), mr.Name())
3692					if sel == nil {
3693						continue
3694					}
3695					ml := sel.Obj().(*types.Func)
3696					if types.AssignableTo(ml.Type(), mr.Type()) {
3697						continue
3698					}
3699
3700					wrong = append(wrong, entry{ml, mr})
3701				}
3702
3703				if len(wrong) != 0 {
3704					s := fmt.Sprintf("impossible type assertion; %s and %s contradict each other:",
3705						types.TypeString(left, types.RelativeTo(pass.Pkg)),
3706						types.TypeString(right, types.RelativeTo(pass.Pkg)))
3707					for _, e := range wrong {
3708						s += fmt.Sprintf("\n\twrong type for %s method", e.l.Name())
3709						s += fmt.Sprintf("\n\t\thave %s", e.l.Type())
3710						s += fmt.Sprintf("\n\t\twant %s", e.r.Type())
3711					}
3712					report.Report(pass, assert, s)
3713				}
3714			}
3715		}
3716	}
3717	return nil, nil
3718}
3719
3720func checkWithValueKey(call *Call) {
3721	arg := call.Args[1]
3722	T := arg.Value.Value.Type()
3723	if T, ok := T.(*types.Basic); ok {
3724		arg.Invalid(
3725			fmt.Sprintf("should not use built-in type %s as key for value; define your own type to avoid collisions", T))
3726	}
3727	if !types.Comparable(T) {
3728		arg.Invalid(fmt.Sprintf("keys used with context.WithValue must be comparable, but type %s is not comparable", T))
3729	}
3730}
3731
3732func CheckMaybeNil(pass *analysis.Pass) (interface{}, error) {
3733	// This is an extremely trivial check that doesn't try to reason
3734	// about control flow. That is, phis and sigmas do not propagate
3735	// any information. As such, we can flag this:
3736	//
3737	// 	_ = *x
3738	// 	if x == nil { return }
3739	//
3740	// but we cannot flag this:
3741	//
3742	// 	if x == nil { println(x) }
3743	// 	_ = *x
3744	//
3745	// nor many other variations of conditional uses of or assignments to x.
3746	//
3747	// However, even this trivial implementation finds plenty of
3748	// real-world bugs, such as dereference before nil pointer check,
3749	// or using t.Error instead of t.Fatal when encountering nil
3750	// pointers.
3751	//
3752	// On the flip side, our naive implementation avoids false positives in branches, such as
3753	//
3754	// 	if x != nil { _ = *x }
3755	//
3756	// due to the same lack of propagating information through sigma
3757	// nodes. x inside the branch will be independent of the x in the
3758	// nil pointer check.
3759	//
3760	//
3761	// We could implement a more powerful check, but then we'd be
3762	// getting false positives instead of false negatives because
3763	// we're incapable of deducing relationships between variables.
3764	// For example, a function might return a pointer and an error,
3765	// and the error being nil guarantees that the pointer is not nil.
3766	// Depending on the surrounding code, the pointer may still end up
3767	// being checked against nil in one place, and guarded by a check
3768	// on the error in another, which would lead to us marking some
3769	// loads as unsafe.
3770	//
3771	// Unfortunately, simply hard-coding the relationship between
3772	// return values wouldn't eliminate all false positives, either.
3773	// Many other more subtle relationships exist. An abridged example
3774	// from real code:
3775	//
3776	// if a == nil && b == nil { return }
3777	// c := fn(a)
3778	// if c != "" { _ = *a }
3779	//
3780	// where `fn` is guaranteed to return a non-empty string if a
3781	// isn't nil.
3782	//
3783	// We choose to err on the side of false negatives.
3784
3785	isNilConst := func(v ir.Value) bool {
3786		if code.IsPointerLike(v.Type()) {
3787			if k, ok := v.(*ir.Const); ok {
3788				return k.IsNil()
3789			}
3790		}
3791		return false
3792	}
3793
3794	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
3795		maybeNil := map[ir.Value]ir.Instruction{}
3796		for _, b := range fn.Blocks {
3797			for _, instr := range b.Instrs {
3798				if instr, ok := instr.(*ir.BinOp); ok {
3799					var ptr ir.Value
3800					if isNilConst(instr.X) {
3801						ptr = instr.Y
3802					} else if isNilConst(instr.Y) {
3803						ptr = instr.X
3804					}
3805					maybeNil[ptr] = instr
3806				}
3807			}
3808		}
3809
3810		for _, b := range fn.Blocks {
3811			for _, instr := range b.Instrs {
3812				var ptr ir.Value
3813				switch instr := instr.(type) {
3814				case *ir.Load:
3815					ptr = instr.X
3816				case *ir.Store:
3817					ptr = instr.Addr
3818				case *ir.IndexAddr:
3819					ptr = instr.X
3820				case *ir.FieldAddr:
3821					ptr = instr.X
3822				}
3823				if ptr != nil {
3824					switch ptr.(type) {
3825					case *ir.Alloc, *ir.FieldAddr, *ir.IndexAddr:
3826						// these cannot be nil
3827						continue
3828					}
3829					if r, ok := maybeNil[ptr]; ok {
3830						report.Report(pass, instr, "possible nil pointer dereference",
3831							report.Related(r, "this check suggests that the pointer can be nil"))
3832					}
3833				}
3834			}
3835		}
3836	}
3837
3838	return nil, nil
3839}
3840
3841var checkAddressIsNilQ = pattern.MustParse(
3842	`(BinaryExpr
3843		(UnaryExpr "&" _)
3844		(Or "==" "!=")
3845		(Builtin "nil"))`)
3846
3847func CheckAddressIsNil(pass *analysis.Pass) (interface{}, error) {
3848	fn := func(node ast.Node) {
3849		_, ok := Match(pass, checkAddressIsNilQ, node)
3850		if !ok {
3851			return
3852		}
3853		report.Report(pass, node, "the address of a variable cannot be nil")
3854	}
3855	code.Preorder(pass, fn, (*ast.BinaryExpr)(nil))
3856	return nil, nil
3857}
3858