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