github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/analysis/passes/printf/printf.go (about)

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