...
Run Format

Source file src/cmd/vet/print.go

Documentation: cmd/vet

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

View as plain text