...

Source file src/pkg/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go

     1	// Copyright 2010 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// This file contains the printf-checker.
     6	
     7	package printf
     8	
     9	import (
    10		"bytes"
    11		"fmt"
    12		"go/ast"
    13		"go/constant"
    14		"go/token"
    15		"go/types"
    16		"regexp"
    17		"sort"
    18		"strconv"
    19		"strings"
    20		"unicode/utf8"
    21	
    22		"golang.org/x/tools/go/analysis"
    23		"golang.org/x/tools/go/analysis/passes/inspect"
    24		"golang.org/x/tools/go/analysis/passes/internal/analysisutil"
    25		"golang.org/x/tools/go/ast/inspector"
    26		"golang.org/x/tools/go/types/typeutil"
    27	)
    28	
    29	func init() {
    30		Analyzer.Flags.Var(isPrint, "funcs", "comma-separated list of print function names to check")
    31	}
    32	
    33	var Analyzer = &analysis.Analyzer{
    34		Name:      "printf",
    35		Doc:       doc,
    36		Requires:  []*analysis.Analyzer{inspect.Analyzer},
    37		Run:       run,
    38		FactTypes: []analysis.Fact{new(isWrapper)},
    39	}
    40	
    41	const doc = `check consistency of Printf format strings and arguments
    42	
    43	The check applies to known functions (for example, those in package fmt)
    44	as well as any detected wrappers of known functions.
    45	
    46	A function that wants to avail itself of printf checking but is not
    47	found by this analyzer's heuristics (for example, due to use of
    48	dynamic calls) can insert a bogus call:
    49	
    50		if false {
    51			_ = fmt.Sprintf(format, args...) // enable printf checking
    52		}
    53	
    54	The -funcs flag specifies a comma-separated list of names of additional
    55	known formatting functions or methods. If the name contains a period,
    56	it must denote a specific function using one of the following forms:
    57	
    58		dir/pkg.Function
    59		dir/pkg.Type.Method
    60		(*dir/pkg.Type).Method
    61	
    62	Otherwise the name is interpreted as a case-insensitive unqualified
    63	identifier such as "errorf". Either way, if a listed name ends in f, the
    64	function is assumed to be Printf-like, taking a format string before the
    65	argument list. Otherwise it is assumed to be Print-like, taking a list
    66	of arguments with no format string.
    67	`
    68	
    69	// isWrapper is a fact indicating that a function is a print or printf wrapper.
    70	type isWrapper struct{ Printf bool }
    71	
    72	func (f *isWrapper) AFact() {}
    73	
    74	func (f *isWrapper) String() string {
    75		if f.Printf {
    76			return "printfWrapper"
    77		} else {
    78			return "printWrapper"
    79		}
    80	}
    81	
    82	func run(pass *analysis.Pass) (interface{}, error) {
    83		findPrintfLike(pass)
    84		checkCall(pass)
    85		return nil, nil
    86	}
    87	
    88	type printfWrapper struct {
    89		obj     *types.Func
    90		fdecl   *ast.FuncDecl
    91		format  *types.Var
    92		args    *types.Var
    93		callers []printfCaller
    94		failed  bool // if true, not a printf wrapper
    95	}
    96	
    97	type printfCaller struct {
    98		w    *printfWrapper
    99		call *ast.CallExpr
   100	}
   101	
   102	// maybePrintfWrapper decides whether decl (a declared function) may be a wrapper
   103	// around a fmt.Printf or fmt.Print function. If so it returns a printfWrapper
   104	// function describing the declaration. Later processing will analyze the
   105	// graph of potential printf wrappers to pick out the ones that are true wrappers.
   106	// A function may be a Printf or Print wrapper if its last argument is ...interface{}.
   107	// If the next-to-last argument is a string, then this may be a Printf wrapper.
   108	// Otherwise it may be a Print wrapper.
   109	func maybePrintfWrapper(info *types.Info, decl ast.Decl) *printfWrapper {
   110		// Look for functions with final argument type ...interface{}.
   111		fdecl, ok := decl.(*ast.FuncDecl)
   112		if !ok || fdecl.Body == nil {
   113			return nil
   114		}
   115		fn := info.Defs[fdecl.Name].(*types.Func)
   116	
   117		sig := fn.Type().(*types.Signature)
   118		if !sig.Variadic() {
   119			return nil // not variadic
   120		}
   121	
   122		params := sig.Params()
   123		nparams := params.Len() // variadic => nonzero
   124	
   125		args := params.At(nparams - 1)
   126		iface, ok := args.Type().(*types.Slice).Elem().(*types.Interface)
   127		if !ok || !iface.Empty() {
   128			return nil // final (args) param is not ...interface{}
   129		}
   130	
   131		// Is second last param 'format string'?
   132		var format *types.Var
   133		if nparams >= 2 {
   134			if p := params.At(nparams - 2); p.Type() == types.Typ[types.String] {
   135				format = p
   136			}
   137		}
   138	
   139		return &printfWrapper{
   140			obj:    fn,
   141			fdecl:  fdecl,
   142			format: format,
   143			args:   args,
   144		}
   145	}
   146	
   147	// findPrintfLike scans the entire package to find printf-like functions.
   148	func findPrintfLike(pass *analysis.Pass) (interface{}, error) {
   149		// Gather potential wrappers and call graph between them.
   150		byObj := make(map[*types.Func]*printfWrapper)
   151		var wrappers []*printfWrapper
   152		for _, file := range pass.Files {
   153			for _, decl := range file.Decls {
   154				w := maybePrintfWrapper(pass.TypesInfo, decl)
   155				if w == nil {
   156					continue
   157				}
   158				byObj[w.obj] = w
   159				wrappers = append(wrappers, w)
   160			}
   161		}
   162	
   163		// Walk the graph to figure out which are really printf wrappers.
   164		for _, w := range wrappers {
   165			// Scan function for calls that could be to other printf-like functions.
   166			ast.Inspect(w.fdecl.Body, func(n ast.Node) bool {
   167				if w.failed {
   168					return false
   169				}
   170	
   171				// TODO: Relax these checks; issue 26555.
   172				if assign, ok := n.(*ast.AssignStmt); ok {
   173					for _, lhs := range assign.Lhs {
   174						if match(pass.TypesInfo, lhs, w.format) ||
   175							match(pass.TypesInfo, lhs, w.args) {
   176							// Modifies the format
   177							// string or args in
   178							// some way, so not a
   179							// simple wrapper.
   180							w.failed = true
   181							return false
   182						}
   183					}
   184				}
   185				if un, ok := n.(*ast.UnaryExpr); ok && un.Op == token.AND {
   186					if match(pass.TypesInfo, un.X, w.format) ||
   187						match(pass.TypesInfo, un.X, w.args) {
   188						// Taking the address of the
   189						// format string or args,
   190						// so not a simple wrapper.
   191						w.failed = true
   192						return false
   193					}
   194				}
   195	
   196				call, ok := n.(*ast.CallExpr)
   197				if !ok || len(call.Args) == 0 || !match(pass.TypesInfo, call.Args[len(call.Args)-1], w.args) {
   198					return true
   199				}
   200	
   201				fn, kind := printfNameAndKind(pass, call)
   202				if kind != 0 {
   203					checkPrintfFwd(pass, w, call, kind)
   204					return true
   205				}
   206	
   207				// If the call is to another function in this package,
   208				// maybe we will find out it is printf-like later.
   209				// Remember this call for later checking.
   210				if fn != nil && fn.Pkg() == pass.Pkg && byObj[fn] != nil {
   211					callee := byObj[fn]
   212					callee.callers = append(callee.callers, printfCaller{w, call})
   213				}
   214	
   215				return true
   216			})
   217		}
   218		return nil, nil
   219	}
   220	
   221	func match(info *types.Info, arg ast.Expr, param *types.Var) bool {
   222		id, ok := arg.(*ast.Ident)
   223		return ok && info.ObjectOf(id) == param
   224	}
   225	
   226	const (
   227		kindPrintf = 1
   228		kindPrint  = 2
   229	)
   230	
   231	// checkPrintfFwd checks that a printf-forwarding wrapper is forwarding correctly.
   232	// It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...).
   233	func checkPrintfFwd(pass *analysis.Pass, w *printfWrapper, call *ast.CallExpr, kind int) {
   234		matched := kind == kindPrint ||
   235			kind == kindPrintf && len(call.Args) >= 2 && match(pass.TypesInfo, call.Args[len(call.Args)-2], w.format)
   236		if !matched {
   237			return
   238		}
   239	
   240		if !call.Ellipsis.IsValid() {
   241			typ, ok := pass.TypesInfo.Types[call.Fun].Type.(*types.Signature)
   242			if !ok {
   243				return
   244			}
   245			if len(call.Args) > typ.Params().Len() {
   246				// If we're passing more arguments than what the
   247				// print/printf function can take, adding an ellipsis
   248				// would break the program. For example:
   249				//
   250				//   func foo(arg1 string, arg2 ...interface{} {
   251				//       fmt.Printf("%s %v", arg1, arg2)
   252				//   }
   253				return
   254			}
   255			desc := "printf"
   256			if kind == kindPrint {
   257				desc = "print"
   258			}
   259			pass.Reportf(call.Pos(), "missing ... in args forwarded to %s-like function", desc)
   260			return
   261		}
   262		fn := w.obj
   263		var fact isWrapper
   264		if !pass.ImportObjectFact(fn, &fact) {
   265			fact.Printf = kind == kindPrintf
   266			pass.ExportObjectFact(fn, &fact)
   267			for _, caller := range w.callers {
   268				checkPrintfFwd(pass, caller.w, caller.call, kind)
   269			}
   270		}
   271	}
   272	
   273	// isPrint records the print functions.
   274	// If a key ends in 'f' then it is assumed to be a formatted print.
   275	//
   276	// Keys are either values returned by (*types.Func).FullName,
   277	// or case-insensitive identifiers such as "errorf".
   278	//
   279	// The -funcs flag adds to this set.
   280	//
   281	// The set below includes facts for many important standard library
   282	// functions, even though the analysis is capable of deducing that, for
   283	// example, fmt.Printf forwards to fmt.Fprintf. We avoid relying on the
   284	// driver applying analyzers to standard packages because "go vet" does
   285	// not do so with gccgo, and nor do some other build systems.
   286	// TODO(adonovan): eliminate the redundant facts once this restriction
   287	// is lifted.
   288	//
   289	var isPrint = stringSet{
   290		"fmt.Errorf":   true,
   291		"fmt.Fprint":   true,
   292		"fmt.Fprintf":  true,
   293		"fmt.Fprintln": true,
   294		"fmt.Print":    true,
   295		"fmt.Printf":   true,
   296		"fmt.Println":  true,
   297		"fmt.Sprint":   true,
   298		"fmt.Sprintf":  true,
   299		"fmt.Sprintln": true,
   300	
   301		"runtime/trace.Logf": true,
   302	
   303		"log.Print":             true,
   304		"log.Printf":            true,
   305		"log.Println":           true,
   306		"log.Fatal":             true,
   307		"log.Fatalf":            true,
   308		"log.Fatalln":           true,
   309		"log.Panic":             true,
   310		"log.Panicf":            true,
   311		"log.Panicln":           true,
   312		"(*log.Logger).Fatal":   true,
   313		"(*log.Logger).Fatalf":  true,
   314		"(*log.Logger).Fatalln": true,
   315		"(*log.Logger).Panic":   true,
   316		"(*log.Logger).Panicf":  true,
   317		"(*log.Logger).Panicln": true,
   318		"(*log.Logger).Print":   true,
   319		"(*log.Logger).Printf":  true,
   320		"(*log.Logger).Println": true,
   321	
   322		"(*testing.common).Error":  true,
   323		"(*testing.common).Errorf": true,
   324		"(*testing.common).Fatal":  true,
   325		"(*testing.common).Fatalf": true,
   326		"(*testing.common).Log":    true,
   327		"(*testing.common).Logf":   true,
   328		"(*testing.common).Skip":   true,
   329		"(*testing.common).Skipf":  true,
   330		// *testing.T and B are detected by induction, but testing.TB is
   331		// an interface and the inference can't follow dynamic calls.
   332		"(testing.TB).Error":  true,
   333		"(testing.TB).Errorf": true,
   334		"(testing.TB).Fatal":  true,
   335		"(testing.TB).Fatalf": true,
   336		"(testing.TB).Log":    true,
   337		"(testing.TB).Logf":   true,
   338		"(testing.TB).Skip":   true,
   339		"(testing.TB).Skipf":  true,
   340	}
   341	
   342	// formatString returns the format string argument and its index within
   343	// the given printf-like call expression.
   344	//
   345	// The last parameter before variadic arguments is assumed to be
   346	// a format string.
   347	//
   348	// The first string literal or string constant is assumed to be a format string
   349	// if the call's signature cannot be determined.
   350	//
   351	// If it cannot find any format string parameter, it returns ("", -1).
   352	func formatString(pass *analysis.Pass, call *ast.CallExpr) (format string, idx int) {
   353		typ := pass.TypesInfo.Types[call.Fun].Type
   354		if typ != nil {
   355			if sig, ok := typ.(*types.Signature); ok {
   356				if !sig.Variadic() {
   357					// Skip checking non-variadic functions.
   358					return "", -1
   359				}
   360				idx := sig.Params().Len() - 2
   361				if idx < 0 {
   362					// Skip checking variadic functions without
   363					// fixed arguments.
   364					return "", -1
   365				}
   366				s, ok := stringConstantArg(pass, call, idx)
   367				if !ok {
   368					// The last argument before variadic args isn't a string.
   369					return "", -1
   370				}
   371				return s, idx
   372			}
   373		}
   374	
   375		// Cannot determine call's signature. Fall back to scanning for the first
   376		// string constant in the call.
   377		for idx := range call.Args {
   378			if s, ok := stringConstantArg(pass, call, idx); ok {
   379				return s, idx
   380			}
   381			if pass.TypesInfo.Types[call.Args[idx]].Type == types.Typ[types.String] {
   382				// Skip checking a call with a non-constant format
   383				// string argument, since its contents are unavailable
   384				// for validation.
   385				return "", -1
   386			}
   387		}
   388		return "", -1
   389	}
   390	
   391	// stringConstantArg returns call's string constant argument at the index idx.
   392	//
   393	// ("", false) is returned if call's argument at the index idx isn't a string
   394	// constant.
   395	func stringConstantArg(pass *analysis.Pass, call *ast.CallExpr, idx int) (string, bool) {
   396		if idx >= len(call.Args) {
   397			return "", false
   398		}
   399		arg := call.Args[idx]
   400		lit := pass.TypesInfo.Types[arg].Value
   401		if lit != nil && lit.Kind() == constant.String {
   402			return constant.StringVal(lit), true
   403		}
   404		return "", false
   405	}
   406	
   407	// checkCall triggers the print-specific checks if the call invokes a print function.
   408	func checkCall(pass *analysis.Pass) {
   409		inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
   410		nodeFilter := []ast.Node{
   411			(*ast.CallExpr)(nil),
   412		}
   413		inspect.Preorder(nodeFilter, func(n ast.Node) {
   414			call := n.(*ast.CallExpr)
   415			fn, kind := printfNameAndKind(pass, call)
   416			switch kind {
   417			case kindPrintf:
   418				checkPrintf(pass, call, fn)
   419			case kindPrint:
   420				checkPrint(pass, call, fn)
   421			}
   422		})
   423	}
   424	
   425	func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, kind int) {
   426		fn, _ = typeutil.Callee(pass.TypesInfo, call).(*types.Func)
   427		if fn == nil {
   428			return nil, 0
   429		}
   430	
   431		var fact isWrapper
   432		if pass.ImportObjectFact(fn, &fact) {
   433			if fact.Printf {
   434				return fn, kindPrintf
   435			} else {
   436				return fn, kindPrint
   437			}
   438		}
   439	
   440		_, ok := isPrint[fn.FullName()]
   441		if !ok {
   442			// Next look up just "printf", for use with -printf.funcs.
   443			_, ok = isPrint[strings.ToLower(fn.Name())]
   444		}
   445		if ok {
   446			if strings.HasSuffix(fn.Name(), "f") {
   447				kind = kindPrintf
   448			} else {
   449				kind = kindPrint
   450			}
   451		}
   452		return fn, kind
   453	}
   454	
   455	// isFormatter reports whether t satisfies fmt.Formatter.
   456	// The only interface method to look for is "Format(State, rune)".
   457	func isFormatter(typ types.Type) bool {
   458		obj, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Format")
   459		fn, ok := obj.(*types.Func)
   460		if !ok {
   461			return false
   462		}
   463		sig := fn.Type().(*types.Signature)
   464		return sig.Params().Len() == 2 &&
   465			sig.Results().Len() == 0 &&
   466			isNamed(sig.Params().At(0).Type(), "fmt", "State") &&
   467			types.Identical(sig.Params().At(1).Type(), types.Typ[types.Rune])
   468	}
   469	
   470	func isNamed(T types.Type, pkgpath, name string) bool {
   471		named, ok := T.(*types.Named)
   472		return ok && named.Obj().Pkg().Path() == pkgpath && named.Obj().Name() == name
   473	}
   474	
   475	// formatState holds the parsed representation of a printf directive such as "%3.*[4]d".
   476	// It is constructed by parsePrintfVerb.
   477	type formatState struct {
   478		verb     rune   // the format verb: 'd' for "%d"
   479		format   string // the full format directive from % through verb, "%.3d".
   480		name     string // Printf, Sprintf etc.
   481		flags    []byte // the list of # + etc.
   482		argNums  []int  // the successive argument numbers that are consumed, adjusted to refer to actual arg in call
   483		firstArg int    // Index of first argument after the format in the Printf call.
   484		// Used only during parse.
   485		pass         *analysis.Pass
   486		call         *ast.CallExpr
   487		argNum       int  // Which argument we're expecting to format now.
   488		hasIndex     bool // Whether the argument is indexed.
   489		indexPending bool // Whether we have an indexed argument that has not resolved.
   490		nbytes       int  // number of bytes of the format string consumed.
   491	}
   492	
   493	// checkPrintf checks a call to a formatted print routine such as Printf.
   494	func checkPrintf(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) {
   495		format, idx := formatString(pass, call)
   496		if idx < 0 {
   497			if false {
   498				pass.Reportf(call.Lparen, "can't check non-constant format in call to %s", fn.Name())
   499			}
   500			return
   501		}
   502	
   503		firstArg := idx + 1 // Arguments are immediately after format string.
   504		if !strings.Contains(format, "%") {
   505			if len(call.Args) > firstArg {
   506				pass.Reportf(call.Lparen, "%s call has arguments but no formatting directives", fn.Name())
   507			}
   508			return
   509		}
   510		// Hard part: check formats against args.
   511		argNum := firstArg
   512		maxArgNum := firstArg
   513		anyIndex := false
   514		for i, w := 0, 0; i < len(format); i += w {
   515			w = 1
   516			if format[i] != '%' {
   517				continue
   518			}
   519			state := parsePrintfVerb(pass, call, fn.Name(), format[i:], firstArg, argNum)
   520			if state == nil {
   521				return
   522			}
   523			w = len(state.format)
   524			if !okPrintfArg(pass, call, state) { // One error per format is enough.
   525				return
   526			}
   527			if state.hasIndex {
   528				anyIndex = true
   529			}
   530			if len(state.argNums) > 0 {
   531				// Continue with the next sequential argument.
   532				argNum = state.argNums[len(state.argNums)-1] + 1
   533			}
   534			for _, n := range state.argNums {
   535				if n >= maxArgNum {
   536					maxArgNum = n + 1
   537				}
   538			}
   539		}
   540		// Dotdotdot is hard.
   541		if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 {
   542			return
   543		}
   544		// If any formats are indexed, extra arguments are ignored.
   545		if anyIndex {
   546			return
   547		}
   548		// There should be no leftover arguments.
   549		if maxArgNum != len(call.Args) {
   550			expect := maxArgNum - firstArg
   551			numArgs := len(call.Args) - firstArg
   552			pass.Reportf(call.Pos(), "%s call needs %v but has %v", fn.Name(), count(expect, "arg"), count(numArgs, "arg"))
   553		}
   554	}
   555	
   556	// parseFlags accepts any printf flags.
   557	func (s *formatState) parseFlags() {
   558		for s.nbytes < len(s.format) {
   559			switch c := s.format[s.nbytes]; c {
   560			case '#', '0', '+', '-', ' ':
   561				s.flags = append(s.flags, c)
   562				s.nbytes++
   563			default:
   564				return
   565			}
   566		}
   567	}
   568	
   569	// scanNum advances through a decimal number if present.
   570	func (s *formatState) scanNum() {
   571		for ; s.nbytes < len(s.format); s.nbytes++ {
   572			c := s.format[s.nbytes]
   573			if c < '0' || '9' < c {
   574				return
   575			}
   576		}
   577	}
   578	
   579	// parseIndex scans an index expression. It returns false if there is a syntax error.
   580	func (s *formatState) parseIndex() bool {
   581		if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' {
   582			return true
   583		}
   584		// Argument index present.
   585		s.nbytes++ // skip '['
   586		start := s.nbytes
   587		s.scanNum()
   588		ok := true
   589		if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' {
   590			ok = false
   591			s.nbytes = strings.Index(s.format, "]")
   592			if s.nbytes < 0 {
   593				s.pass.Reportf(s.call.Pos(), "%s format %s is missing closing ]", s.name, s.format)
   594				return false
   595			}
   596		}
   597		arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32)
   598		if err != nil || !ok || arg32 <= 0 || arg32 > int64(len(s.call.Args)-s.firstArg) {
   599			s.pass.Reportf(s.call.Pos(), "%s format has invalid argument index [%s]", s.name, s.format[start:s.nbytes])
   600			return false
   601		}
   602		s.nbytes++ // skip ']'
   603		arg := int(arg32)
   604		arg += s.firstArg - 1 // We want to zero-index the actual arguments.
   605		s.argNum = arg
   606		s.hasIndex = true
   607		s.indexPending = true
   608		return true
   609	}
   610	
   611	// parseNum scans a width or precision (or *). It returns false if there's a bad index expression.
   612	func (s *formatState) parseNum() bool {
   613		if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' {
   614			if s.indexPending { // Absorb it.
   615				s.indexPending = false
   616			}
   617			s.nbytes++
   618			s.argNums = append(s.argNums, s.argNum)
   619			s.argNum++
   620		} else {
   621			s.scanNum()
   622		}
   623		return true
   624	}
   625	
   626	// parsePrecision scans for a precision. It returns false if there's a bad index expression.
   627	func (s *formatState) parsePrecision() bool {
   628		// If there's a period, there may be a precision.
   629		if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' {
   630			s.flags = append(s.flags, '.') // Treat precision as a flag.
   631			s.nbytes++
   632			if !s.parseIndex() {
   633				return false
   634			}
   635			if !s.parseNum() {
   636				return false
   637			}
   638		}
   639		return true
   640	}
   641	
   642	// parsePrintfVerb looks the formatting directive that begins the format string
   643	// and returns a formatState that encodes what the directive wants, without looking
   644	// at the actual arguments present in the call. The result is nil if there is an error.
   645	func parsePrintfVerb(pass *analysis.Pass, call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState {
   646		state := &formatState{
   647			format:   format,
   648			name:     name,
   649			flags:    make([]byte, 0, 5),
   650			argNum:   argNum,
   651			argNums:  make([]int, 0, 1),
   652			nbytes:   1, // There's guaranteed to be a percent sign.
   653			firstArg: firstArg,
   654			pass:     pass,
   655			call:     call,
   656		}
   657		// There may be flags.
   658		state.parseFlags()
   659		// There may be an index.
   660		if !state.parseIndex() {
   661			return nil
   662		}
   663		// There may be a width.
   664		if !state.parseNum() {
   665			return nil
   666		}
   667		// There may be a precision.
   668		if !state.parsePrecision() {
   669			return nil
   670		}
   671		// Now a verb, possibly prefixed by an index (which we may already have).
   672		if !state.indexPending && !state.parseIndex() {
   673			return nil
   674		}
   675		if state.nbytes == len(state.format) {
   676			pass.Reportf(call.Pos(), "%s format %s is missing verb at end of string", name, state.format)
   677			return nil
   678		}
   679		verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:])
   680		state.verb = verb
   681		state.nbytes += w
   682		if verb != '%' {
   683			state.argNums = append(state.argNums, state.argNum)
   684		}
   685		state.format = state.format[:state.nbytes]
   686		return state
   687	}
   688	
   689	// printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask.
   690	type printfArgType int
   691	
   692	const (
   693		argBool printfArgType = 1 << iota
   694		argInt
   695		argRune
   696		argString
   697		argFloat
   698		argComplex
   699		argPointer
   700		anyType printfArgType = ^0
   701	)
   702	
   703	type printVerb struct {
   704		verb  rune   // User may provide verb through Formatter; could be a rune.
   705		flags string // known flags are all ASCII
   706		typ   printfArgType
   707	}
   708	
   709	// Common flag sets for printf verbs.
   710	const (
   711		noFlag       = ""
   712		numFlag      = " -+.0"
   713		sharpNumFlag = " -+.0#"
   714		allFlags     = " -+.0#"
   715	)
   716	
   717	// printVerbs identifies which flags are known to printf for each verb.
   718	var printVerbs = []printVerb{
   719		// '-' is a width modifier, always valid.
   720		// '.' is a precision for float, max width for strings.
   721		// '+' is required sign for numbers, Go format for %v.
   722		// '#' is alternate format for several verbs.
   723		// ' ' is spacer for numbers
   724		{'%', noFlag, 0},
   725		{'b', numFlag, argInt | argFloat | argComplex | argPointer},
   726		{'c', "-", argRune | argInt},
   727		{'d', numFlag, argInt | argPointer},
   728		{'e', sharpNumFlag, argFloat | argComplex},
   729		{'E', sharpNumFlag, argFloat | argComplex},
   730		{'f', sharpNumFlag, argFloat | argComplex},
   731		{'F', sharpNumFlag, argFloat | argComplex},
   732		{'g', sharpNumFlag, argFloat | argComplex},
   733		{'G', sharpNumFlag, argFloat | argComplex},
   734		{'o', sharpNumFlag, argInt | argPointer},
   735		{'p', "-#", argPointer},
   736		{'q', " -+.0#", argRune | argInt | argString},
   737		{'s', " -+.0", argString},
   738		{'t', "-", argBool},
   739		{'T', "-", anyType},
   740		{'U', "-#", argRune | argInt},
   741		{'v', allFlags, anyType},
   742		{'w', noFlag, anyType},
   743		{'x', sharpNumFlag, argRune | argInt | argString | argPointer},
   744		{'X', sharpNumFlag, argRune | argInt | argString | argPointer},
   745	}
   746	
   747	// okPrintfArg compares the formatState to the arguments actually present,
   748	// reporting any discrepancies it can discern. If the final argument is ellipsissed,
   749	// there's little it can do for that.
   750	func okPrintfArg(pass *analysis.Pass, call *ast.CallExpr, state *formatState) (ok bool) {
   751		var v printVerb
   752		found := false
   753		// Linear scan is fast enough for a small list.
   754		for _, v = range printVerbs {
   755			if v.verb == state.verb {
   756				found = true
   757				break
   758			}
   759		}
   760	
   761		// Does current arg implement fmt.Formatter?
   762		formatter := false
   763		if state.argNum < len(call.Args) {
   764			if tv, ok := pass.TypesInfo.Types[call.Args[state.argNum]]; ok {
   765				formatter = isFormatter(tv.Type)
   766			}
   767		}
   768	
   769		if !formatter {
   770			if !found {
   771				pass.Reportf(call.Pos(), "%s format %s has unknown verb %c", state.name, state.format, state.verb)
   772				return false
   773			}
   774			for _, flag := range state.flags {
   775				// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11.
   776				// See issues 23598 and 23605.
   777				if flag == '0' {
   778					continue
   779				}
   780				if !strings.ContainsRune(v.flags, rune(flag)) {
   781					pass.Reportf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag)
   782					return false
   783				}
   784			}
   785		}
   786		// Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all
   787		// but the final arg must be an integer.
   788		trueArgs := 1
   789		if state.verb == '%' {
   790			trueArgs = 0
   791		}
   792		nargs := len(state.argNums)
   793		for i := 0; i < nargs-trueArgs; i++ {
   794			argNum := state.argNums[i]
   795			if !argCanBeChecked(pass, call, i, state) {
   796				return
   797			}
   798			arg := call.Args[argNum]
   799			if !matchArgType(pass, argInt, nil, arg) {
   800				pass.Reportf(call.Pos(), "%s format %s uses non-int %s as argument of *", state.name, state.format, analysisutil.Format(pass.Fset, arg))
   801				return false
   802			}
   803		}
   804	
   805		if state.verb == '%' || formatter {
   806			return true
   807		}
   808		argNum := state.argNums[len(state.argNums)-1]
   809		if !argCanBeChecked(pass, call, len(state.argNums)-1, state) {
   810			return false
   811		}
   812		arg := call.Args[argNum]
   813		if isFunctionValue(pass, arg) && state.verb != 'p' && state.verb != 'T' {
   814			pass.Reportf(call.Pos(), "%s format %s arg %s is a func value, not called", state.name, state.format, analysisutil.Format(pass.Fset, arg))
   815			return false
   816		}
   817		if !matchArgType(pass, v.typ, nil, arg) {
   818			typeString := ""
   819			if typ := pass.TypesInfo.Types[arg].Type; typ != nil {
   820				typeString = typ.String()
   821			}
   822			pass.Reportf(call.Pos(), "%s format %s has arg %s of wrong type %s", state.name, state.format, analysisutil.Format(pass.Fset, arg), typeString)
   823			return false
   824		}
   825		if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && recursiveStringer(pass, arg) {
   826			pass.Reportf(call.Pos(), "%s format %s with arg %s causes recursive String method call", state.name, state.format, analysisutil.Format(pass.Fset, arg))
   827			return false
   828		}
   829		return true
   830	}
   831	
   832	// recursiveStringer reports whether the argument e is a potential
   833	// recursive call to stringer, such as t and &t in these examples:
   834	//
   835	// 	func (t *T) String() string { printf("%s",  t) }
   836	// 	func (t  T) String() string { printf("%s",  t) }
   837	// 	func (t  T) String() string { printf("%s", &t) }
   838	//
   839	func recursiveStringer(pass *analysis.Pass, e ast.Expr) bool {
   840		typ := pass.TypesInfo.Types[e].Type
   841	
   842		// It's unlikely to be a recursive stringer if it has a Format method.
   843		if isFormatter(typ) {
   844			return false
   845		}
   846	
   847		// Does e allow e.String()?
   848		obj, _, _ := types.LookupFieldOrMethod(typ, false, pass.Pkg, "String")
   849		stringMethod, ok := obj.(*types.Func)
   850		if !ok {
   851			return false
   852		}
   853	
   854		// Is the expression e within the body of that String method?
   855		if stringMethod.Pkg() != pass.Pkg || !stringMethod.Scope().Contains(e.Pos()) {
   856			return false
   857		}
   858	
   859		sig := stringMethod.Type().(*types.Signature)
   860		if !isStringer(sig) {
   861			return false
   862		}
   863	
   864		// Is it the receiver r, or &r?
   865		if u, ok := e.(*ast.UnaryExpr); ok && u.Op == token.AND {
   866			e = u.X // strip off & from &r
   867		}
   868		if id, ok := e.(*ast.Ident); ok {
   869			return pass.TypesInfo.Uses[id] == sig.Recv()
   870		}
   871		return false
   872	}
   873	
   874	// isStringer reports whether the method signature matches the String() definition in fmt.Stringer.
   875	func isStringer(sig *types.Signature) bool {
   876		return sig.Params().Len() == 0 &&
   877			sig.Results().Len() == 1 &&
   878			sig.Results().At(0).Type() == types.Typ[types.String]
   879	}
   880	
   881	// isFunctionValue reports whether the expression is a function as opposed to a function call.
   882	// It is almost always a mistake to print a function value.
   883	func isFunctionValue(pass *analysis.Pass, e ast.Expr) bool {
   884		if typ := pass.TypesInfo.Types[e].Type; typ != nil {
   885			_, ok := typ.(*types.Signature)
   886			return ok
   887		}
   888		return false
   889	}
   890	
   891	// argCanBeChecked reports whether the specified argument is statically present;
   892	// it may be beyond the list of arguments or in a terminal slice... argument, which
   893	// means we can't see it.
   894	func argCanBeChecked(pass *analysis.Pass, call *ast.CallExpr, formatArg int, state *formatState) bool {
   895		argNum := state.argNums[formatArg]
   896		if argNum <= 0 {
   897			// Shouldn't happen, so catch it with prejudice.
   898			panic("negative arg num")
   899		}
   900		if argNum < len(call.Args)-1 {
   901			return true // Always OK.
   902		}
   903		if call.Ellipsis.IsValid() {
   904			return false // We just can't tell; there could be many more arguments.
   905		}
   906		if argNum < len(call.Args) {
   907			return true
   908		}
   909		// There are bad indexes in the format or there are fewer arguments than the format needs.
   910		// This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi".
   911		arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed.
   912		pass.Reportf(call.Pos(), "%s format %s reads arg #%d, but call has %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg"))
   913		return false
   914	}
   915	
   916	// printFormatRE is the regexp we match and report as a possible format string
   917	// in the first argument to unformatted prints like fmt.Print.
   918	// We exclude the space flag, so that printing a string like "x % y" is not reported as a format.
   919	var printFormatRE = regexp.MustCompile(`%` + flagsRE + numOptRE + `\.?` + numOptRE + indexOptRE + verbRE)
   920	
   921	const (
   922		flagsRE    = `[+\-#]*`
   923		indexOptRE = `(\[[0-9]+\])?`
   924		numOptRE   = `([0-9]+|` + indexOptRE + `\*)?`
   925		verbRE     = `[bcdefgopqstvxEFGTUX]`
   926	)
   927	
   928	// checkPrint checks a call to an unformatted print routine such as Println.
   929	func checkPrint(pass *analysis.Pass, call *ast.CallExpr, fn *types.Func) {
   930		firstArg := 0
   931		typ := pass.TypesInfo.Types[call.Fun].Type
   932		if typ == nil {
   933			// Skip checking functions with unknown type.
   934			return
   935		}
   936		if sig, ok := typ.(*types.Signature); ok {
   937			if !sig.Variadic() {
   938				// Skip checking non-variadic functions.
   939				return
   940			}
   941			params := sig.Params()
   942			firstArg = params.Len() - 1
   943	
   944			typ := params.At(firstArg).Type()
   945			typ = typ.(*types.Slice).Elem()
   946			it, ok := typ.(*types.Interface)
   947			if !ok || !it.Empty() {
   948				// Skip variadic functions accepting non-interface{} args.
   949				return
   950			}
   951		}
   952		args := call.Args
   953		if len(args) <= firstArg {
   954			// Skip calls without variadic args.
   955			return
   956		}
   957		args = args[firstArg:]
   958	
   959		if firstArg == 0 {
   960			if sel, ok := call.Args[0].(*ast.SelectorExpr); ok {
   961				if x, ok := sel.X.(*ast.Ident); ok {
   962					if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") {
   963						pass.Reportf(call.Pos(), "%s does not take io.Writer but has first arg %s", fn.Name(), analysisutil.Format(pass.Fset, call.Args[0]))
   964					}
   965				}
   966			}
   967		}
   968	
   969		arg := args[0]
   970		if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   971			// Ignore trailing % character in lit.Value.
   972			// The % in "abc 0.0%" couldn't be a formatting directive.
   973			s := strings.TrimSuffix(lit.Value, `%"`)
   974			if strings.Contains(s, "%") {
   975				m := printFormatRE.FindStringSubmatch(s)
   976				if m != nil {
   977					pass.Reportf(call.Pos(), "%s call has possible formatting directive %s", fn.Name(), m[0])
   978				}
   979			}
   980		}
   981		if strings.HasSuffix(fn.Name(), "ln") {
   982			// The last item, if a string, should not have a newline.
   983			arg = args[len(args)-1]
   984			if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING {
   985				str, _ := strconv.Unquote(lit.Value)
   986				if strings.HasSuffix(str, "\n") {
   987					pass.Reportf(call.Pos(), "%s arg list ends with redundant newline", fn.Name())
   988				}
   989			}
   990		}
   991		for _, arg := range args {
   992			if isFunctionValue(pass, arg) {
   993				pass.Reportf(call.Pos(), "%s arg %s is a func value, not called", fn.Name(), analysisutil.Format(pass.Fset, arg))
   994			}
   995			if recursiveStringer(pass, arg) {
   996				pass.Reportf(call.Pos(), "%s arg %s causes recursive call to String method", fn.Name(), analysisutil.Format(pass.Fset, arg))
   997			}
   998		}
   999	}
  1000	
  1001	// count(n, what) returns "1 what" or "N whats"
  1002	// (assuming the plural of what is whats).
  1003	func count(n int, what string) string {
  1004		if n == 1 {
  1005			return "1 " + what
  1006		}
  1007		return fmt.Sprintf("%d %ss", n, what)
  1008	}
  1009	
  1010	// stringSet is a set-of-nonempty-strings-valued flag.
  1011	// Note: elements without a '.' get lower-cased.
  1012	type stringSet map[string]bool
  1013	
  1014	func (ss stringSet) String() string {
  1015		var list []string
  1016		for name := range ss {
  1017			list = append(list, name)
  1018		}
  1019		sort.Strings(list)
  1020		return strings.Join(list, ",")
  1021	}
  1022	
  1023	func (ss stringSet) Set(flag string) error {
  1024		for _, name := range strings.Split(flag, ",") {
  1025			if len(name) == 0 {
  1026				return fmt.Errorf("empty string")
  1027			}
  1028			if !strings.Contains(name, ".") {
  1029				name = strings.ToLower(name)
  1030			}
  1031			ss[name] = true
  1032		}
  1033		return nil
  1034	}
  1035	

View as plain text