github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/vet/print.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 // This file contains the printf-checker. 6 7 package main 8 9 import ( 10 "bytes" 11 "flag" 12 "go/ast" 13 "go/constant" 14 "go/token" 15 "go/types" 16 "strconv" 17 "strings" 18 "unicode/utf8" 19 ) 20 21 var printfuncs = flag.String("printfuncs", "", "comma-separated list of print function names to check") 22 23 func init() { 24 register("printf", 25 "check printf-like invocations", 26 checkFmtPrintfCall, 27 funcDecl, callExpr) 28 } 29 30 func initPrintFlags() { 31 if *printfuncs == "" { 32 return 33 } 34 for _, name := range strings.Split(*printfuncs, ",") { 35 if len(name) == 0 { 36 flag.Usage() 37 } 38 39 // Backwards compatibility: skip optional first argument 40 // index after the colon. 41 if colon := strings.LastIndex(name, ":"); colon > 0 { 42 name = name[:colon] 43 } 44 45 name = strings.ToLower(name) 46 if name[len(name)-1] == 'f' { 47 isFormattedPrint[name] = true 48 } else { 49 isPrint[name] = true 50 } 51 } 52 } 53 54 // isFormattedPrint records the formatted-print functions. Names are 55 // lower-cased so the lookup is case insensitive. 56 var isFormattedPrint = map[string]bool{ 57 "errorf": true, 58 "fatalf": true, 59 "fprintf": true, 60 "logf": true, 61 "panicf": true, 62 "printf": true, 63 "sprintf": true, 64 } 65 66 // isPrint records the unformatted-print functions. Names are lower-cased 67 // so the lookup is case insensitive. 68 var isPrint = map[string]bool{ 69 "error": true, 70 "fatal": true, 71 "fprint": true, 72 "fprintln": true, 73 "log": true, 74 "panic": true, 75 "panicln": true, 76 "print": true, 77 "println": true, 78 "sprint": true, 79 "sprintln": true, 80 } 81 82 // formatString returns the format string argument and its index within 83 // the given printf-like call expression. 84 // 85 // The last parameter before variadic arguments is assumed to be 86 // a format string. 87 // 88 // The first string literal or string constant is assumed to be a format string 89 // if the call's signature cannot be determined. 90 // 91 // If it cannot find any format string parameter, it returns ("", -1). 92 func formatString(f *File, call *ast.CallExpr) (string, int) { 93 typ := f.pkg.types[call.Fun].Type 94 if typ != nil { 95 if sig, ok := typ.(*types.Signature); ok { 96 if !sig.Variadic() { 97 // Skip checking non-variadic functions 98 return "", -1 99 } 100 idx := sig.Params().Len() - 2 101 if idx < 0 { 102 // Skip checking variadic functions without 103 // fixed arguments. 104 return "", -1 105 } 106 s, ok := stringLiteralArg(f, call, idx) 107 if !ok { 108 // The last argument before variadic args isn't a string 109 return "", -1 110 } 111 return s, idx 112 } 113 } 114 115 // Cannot determine call's signature. Fallback to scanning for the first 116 // string argument in the call 117 for idx := range call.Args { 118 if s, ok := stringLiteralArg(f, call, idx); ok { 119 return s, idx 120 } 121 } 122 return "", -1 123 } 124 125 // stringLiteralArg returns call's string constant argument at the index idx. 126 // 127 // ("", false) is returned if call's argument at the index idx isn't a string 128 // literal. 129 func stringLiteralArg(f *File, call *ast.CallExpr, idx int) (string, bool) { 130 if idx >= len(call.Args) { 131 return "", false 132 } 133 arg := call.Args[idx] 134 lit := f.pkg.types[arg].Value 135 if lit != nil && lit.Kind() == constant.String { 136 return constant.StringVal(lit), true 137 } 138 return "", false 139 } 140 141 // checkCall triggers the print-specific checks if the call invokes a print function. 142 func checkFmtPrintfCall(f *File, node ast.Node) { 143 if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) { 144 // Remember we saw this. 145 if f.stringers == nil { 146 f.stringers = make(map[*ast.Object]bool) 147 } 148 if l := d.Recv.List; len(l) == 1 { 149 if n := l[0].Names; len(n) == 1 { 150 f.stringers[n[0].Obj] = true 151 } 152 } 153 return 154 } 155 156 call, ok := node.(*ast.CallExpr) 157 if !ok { 158 return 159 } 160 var Name string 161 switch x := call.Fun.(type) { 162 case *ast.Ident: 163 Name = x.Name 164 case *ast.SelectorExpr: 165 Name = x.Sel.Name 166 default: 167 return 168 } 169 170 name := strings.ToLower(Name) 171 if _, ok := isFormattedPrint[name]; ok { 172 f.checkPrintf(call, Name) 173 return 174 } 175 if _, ok := isPrint[name]; ok { 176 f.checkPrint(call, Name) 177 return 178 } 179 } 180 181 // isStringer returns true if the provided declaration is a "String() string" 182 // method, an implementation of fmt.Stringer. 183 func isStringer(f *File, d *ast.FuncDecl) bool { 184 return d.Recv != nil && d.Name.Name == "String" && d.Type.Results != nil && 185 len(d.Type.Params.List) == 0 && len(d.Type.Results.List) == 1 && 186 f.pkg.types[d.Type.Results.List[0].Type].Type == types.Typ[types.String] 187 } 188 189 // formatState holds the parsed representation of a printf directive such as "%3.*[4]d". 190 // It is constructed by parsePrintfVerb. 191 type formatState struct { 192 verb rune // the format verb: 'd' for "%d" 193 format string // the full format directive from % through verb, "%.3d". 194 name string // Printf, Sprintf etc. 195 flags []byte // the list of # + etc. 196 argNums []int // the successive argument numbers that are consumed, adjusted to refer to actual arg in call 197 indexed bool // whether an indexing expression appears: %[1]d. 198 firstArg int // Index of first argument after the format in the Printf call. 199 // Used only during parse. 200 file *File 201 call *ast.CallExpr 202 argNum int // Which argument we're expecting to format now. 203 indexPending bool // Whether we have an indexed argument that has not resolved. 204 nbytes int // number of bytes of the format string consumed. 205 } 206 207 // checkPrintf checks a call to a formatted print routine such as Printf. 208 func (f *File) checkPrintf(call *ast.CallExpr, name string) { 209 format, idx := formatString(f, call) 210 if idx < 0 { 211 if *verbose { 212 f.Warn(call.Pos(), "can't check non-constant format in call to", name) 213 } 214 return 215 } 216 217 firstArg := idx + 1 // Arguments are immediately after format string. 218 if !strings.Contains(format, "%") { 219 if len(call.Args) > firstArg { 220 f.Badf(call.Pos(), "no formatting directive in %s call", name) 221 } 222 return 223 } 224 // Hard part: check formats against args. 225 argNum := firstArg 226 indexed := false 227 for i, w := 0, 0; i < len(format); i += w { 228 w = 1 229 if format[i] == '%' { 230 state := f.parsePrintfVerb(call, name, format[i:], firstArg, argNum) 231 if state == nil { 232 return 233 } 234 w = len(state.format) 235 if state.indexed { 236 indexed = true 237 } 238 if !f.okPrintfArg(call, state) { // One error per format is enough. 239 return 240 } 241 if len(state.argNums) > 0 { 242 // Continue with the next sequential argument. 243 argNum = state.argNums[len(state.argNums)-1] + 1 244 } 245 } 246 } 247 // Dotdotdot is hard. 248 if call.Ellipsis.IsValid() && argNum >= len(call.Args)-1 { 249 return 250 } 251 // If the arguments were direct indexed, we assume the programmer knows what's up. 252 // Otherwise, there should be no leftover arguments. 253 if !indexed && argNum != len(call.Args) { 254 expect := argNum - firstArg 255 numArgs := len(call.Args) - firstArg 256 f.Badf(call.Pos(), "wrong number of args for format in %s call: %d needed but %d args", name, expect, numArgs) 257 } 258 } 259 260 // parseFlags accepts any printf flags. 261 func (s *formatState) parseFlags() { 262 for s.nbytes < len(s.format) { 263 switch c := s.format[s.nbytes]; c { 264 case '#', '0', '+', '-', ' ': 265 s.flags = append(s.flags, c) 266 s.nbytes++ 267 default: 268 return 269 } 270 } 271 } 272 273 // scanNum advances through a decimal number if present. 274 func (s *formatState) scanNum() { 275 for ; s.nbytes < len(s.format); s.nbytes++ { 276 c := s.format[s.nbytes] 277 if c < '0' || '9' < c { 278 return 279 } 280 } 281 } 282 283 // parseIndex scans an index expression. It returns false if there is a syntax error. 284 func (s *formatState) parseIndex() bool { 285 if s.nbytes == len(s.format) || s.format[s.nbytes] != '[' { 286 return true 287 } 288 // Argument index present. 289 s.indexed = true 290 s.nbytes++ // skip '[' 291 start := s.nbytes 292 s.scanNum() 293 if s.nbytes == len(s.format) || s.nbytes == start || s.format[s.nbytes] != ']' { 294 s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index") 295 return false 296 } 297 arg32, err := strconv.ParseInt(s.format[start:s.nbytes], 10, 32) 298 if err != nil { 299 s.file.Badf(s.call.Pos(), "illegal syntax for printf argument index: %s", err) 300 return false 301 } 302 s.nbytes++ // skip ']' 303 arg := int(arg32) 304 arg += s.firstArg - 1 // We want to zero-index the actual arguments. 305 s.argNum = arg 306 s.indexPending = true 307 return true 308 } 309 310 // parseNum scans a width or precision (or *). It returns false if there's a bad index expression. 311 func (s *formatState) parseNum() bool { 312 if s.nbytes < len(s.format) && s.format[s.nbytes] == '*' { 313 if s.indexPending { // Absorb it. 314 s.indexPending = false 315 } 316 s.nbytes++ 317 s.argNums = append(s.argNums, s.argNum) 318 s.argNum++ 319 } else { 320 s.scanNum() 321 } 322 return true 323 } 324 325 // parsePrecision scans for a precision. It returns false if there's a bad index expression. 326 func (s *formatState) parsePrecision() bool { 327 // If there's a period, there may be a precision. 328 if s.nbytes < len(s.format) && s.format[s.nbytes] == '.' { 329 s.flags = append(s.flags, '.') // Treat precision as a flag. 330 s.nbytes++ 331 if !s.parseIndex() { 332 return false 333 } 334 if !s.parseNum() { 335 return false 336 } 337 } 338 return true 339 } 340 341 // parsePrintfVerb looks the formatting directive that begins the format string 342 // and returns a formatState that encodes what the directive wants, without looking 343 // at the actual arguments present in the call. The result is nil if there is an error. 344 func (f *File) parsePrintfVerb(call *ast.CallExpr, name, format string, firstArg, argNum int) *formatState { 345 state := &formatState{ 346 format: format, 347 name: name, 348 flags: make([]byte, 0, 5), 349 argNum: argNum, 350 argNums: make([]int, 0, 1), 351 nbytes: 1, // There's guaranteed to be a percent sign. 352 indexed: false, 353 firstArg: firstArg, 354 file: f, 355 call: call, 356 } 357 // There may be flags. 358 state.parseFlags() 359 indexPending := false 360 // There may be an index. 361 if !state.parseIndex() { 362 return nil 363 } 364 // There may be a width. 365 if !state.parseNum() { 366 return nil 367 } 368 // There may be a precision. 369 if !state.parsePrecision() { 370 return nil 371 } 372 // Now a verb, possibly prefixed by an index (which we may already have). 373 if !indexPending && !state.parseIndex() { 374 return nil 375 } 376 if state.nbytes == len(state.format) { 377 f.Badf(call.Pos(), "missing verb at end of format string in %s call", name) 378 return nil 379 } 380 verb, w := utf8.DecodeRuneInString(state.format[state.nbytes:]) 381 state.verb = verb 382 state.nbytes += w 383 if verb != '%' { 384 state.argNums = append(state.argNums, state.argNum) 385 } 386 state.format = state.format[:state.nbytes] 387 return state 388 } 389 390 // printfArgType encodes the types of expressions a printf verb accepts. It is a bitmask. 391 type printfArgType int 392 393 const ( 394 argBool printfArgType = 1 << iota 395 argInt 396 argRune 397 argString 398 argFloat 399 argComplex 400 argPointer 401 anyType printfArgType = ^0 402 ) 403 404 type printVerb struct { 405 verb rune // User may provide verb through Formatter; could be a rune. 406 flags string // known flags are all ASCII 407 typ printfArgType 408 } 409 410 // Common flag sets for printf verbs. 411 const ( 412 noFlag = "" 413 numFlag = " -+.0" 414 sharpNumFlag = " -+.0#" 415 allFlags = " -+.0#" 416 ) 417 418 // printVerbs identifies which flags are known to printf for each verb. 419 // TODO: A type that implements Formatter may do what it wants, and vet 420 // will complain incorrectly. 421 var printVerbs = []printVerb{ 422 // '-' is a width modifier, always valid. 423 // '.' is a precision for float, max width for strings. 424 // '+' is required sign for numbers, Go format for %v. 425 // '#' is alternate format for several verbs. 426 // ' ' is spacer for numbers 427 {'%', noFlag, 0}, 428 {'b', numFlag, argInt | argFloat | argComplex}, 429 {'c', "-", argRune | argInt}, 430 {'d', numFlag, argInt}, 431 {'e', numFlag, argFloat | argComplex}, 432 {'E', numFlag, argFloat | argComplex}, 433 {'f', numFlag, argFloat | argComplex}, 434 {'F', numFlag, argFloat | argComplex}, 435 {'g', numFlag, argFloat | argComplex}, 436 {'G', numFlag, argFloat | argComplex}, 437 {'o', sharpNumFlag, argInt}, 438 {'p', "-#", argPointer}, 439 {'q', " -+.0#", argRune | argInt | argString}, 440 {'s', " -+.0", argString}, 441 {'t', "-", argBool}, 442 {'T', "-", anyType}, 443 {'U', "-#", argRune | argInt}, 444 {'v', allFlags, anyType}, 445 {'x', sharpNumFlag, argRune | argInt | argString}, 446 {'X', sharpNumFlag, argRune | argInt | argString}, 447 } 448 449 // okPrintfArg compares the formatState to the arguments actually present, 450 // reporting any discrepancies it can discern. If the final argument is ellipsissed, 451 // there's little it can do for that. 452 func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) { 453 var v printVerb 454 found := false 455 // Linear scan is fast enough for a small list. 456 for _, v = range printVerbs { 457 if v.verb == state.verb { 458 found = true 459 break 460 } 461 } 462 if !found { 463 f.Badf(call.Pos(), "unrecognized printf verb %q", state.verb) 464 return false 465 } 466 for _, flag := range state.flags { 467 if !strings.ContainsRune(v.flags, rune(flag)) { 468 f.Badf(call.Pos(), "unrecognized printf flag for verb %q: %q", state.verb, flag) 469 return false 470 } 471 } 472 // Verb is good. If len(state.argNums)>trueArgs, we have something like %.*s and all 473 // but the final arg must be an integer. 474 trueArgs := 1 475 if state.verb == '%' { 476 trueArgs = 0 477 } 478 nargs := len(state.argNums) 479 for i := 0; i < nargs-trueArgs; i++ { 480 argNum := state.argNums[i] 481 if !f.argCanBeChecked(call, i, true, state) { 482 return 483 } 484 arg := call.Args[argNum] 485 if !f.matchArgType(argInt, nil, arg) { 486 f.Badf(call.Pos(), "arg %s for * in printf format not of type int", f.gofmt(arg)) 487 return false 488 } 489 } 490 if state.verb == '%' { 491 return true 492 } 493 argNum := state.argNums[len(state.argNums)-1] 494 if !f.argCanBeChecked(call, len(state.argNums)-1, false, state) { 495 return false 496 } 497 arg := call.Args[argNum] 498 if f.isFunctionValue(arg) && state.verb != 'p' && state.verb != 'T' { 499 f.Badf(call.Pos(), "arg %s in printf call is a function value, not a function call", f.gofmt(arg)) 500 return false 501 } 502 if !f.matchArgType(v.typ, nil, arg) { 503 typeString := "" 504 if typ := f.pkg.types[arg].Type; typ != nil { 505 typeString = typ.String() 506 } 507 f.Badf(call.Pos(), "arg %s for printf verb %%%c of wrong type: %s", f.gofmt(arg), state.verb, typeString) 508 return false 509 } 510 if v.typ&argString != 0 && v.verb != 'T' && !bytes.Contains(state.flags, []byte{'#'}) && f.recursiveStringer(arg) { 511 f.Badf(call.Pos(), "arg %s for printf causes recursive call to String method", f.gofmt(arg)) 512 return false 513 } 514 return true 515 } 516 517 // recursiveStringer reports whether the provided argument is r or &r for the 518 // fmt.Stringer receiver identifier r. 519 func (f *File) recursiveStringer(e ast.Expr) bool { 520 if len(f.stringers) == 0 { 521 return false 522 } 523 var obj *ast.Object 524 switch e := e.(type) { 525 case *ast.Ident: 526 obj = e.Obj 527 case *ast.UnaryExpr: 528 if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND { 529 obj = id.Obj 530 } 531 } 532 533 // It's unlikely to be a recursive stringer if it has a Format method. 534 if typ := f.pkg.types[e].Type; typ != nil { 535 // Not a perfect match; see issue 6259. 536 if f.hasMethod(typ, "Format") { 537 return false 538 } 539 } 540 541 // We compare the underlying Object, which checks that the identifier 542 // is the one we declared as the receiver for the String method in 543 // which this printf appears. 544 return f.stringers[obj] 545 } 546 547 // isFunctionValue reports whether the expression is a function as opposed to a function call. 548 // It is almost always a mistake to print a function value. 549 func (f *File) isFunctionValue(e ast.Expr) bool { 550 if typ := f.pkg.types[e].Type; typ != nil { 551 _, ok := typ.(*types.Signature) 552 return ok 553 } 554 return false 555 } 556 557 // argCanBeChecked reports whether the specified argument is statically present; 558 // it may be beyond the list of arguments or in a terminal slice... argument, which 559 // means we can't see it. 560 func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, isStar bool, state *formatState) bool { 561 argNum := state.argNums[formatArg] 562 if argNum < 0 { 563 // Shouldn't happen, so catch it with prejudice. 564 panic("negative arg num") 565 } 566 if argNum == 0 { 567 f.Badf(call.Pos(), `index value [0] for %s("%s"); indexes start at 1`, state.name, state.format) 568 return false 569 } 570 if argNum < len(call.Args)-1 { 571 return true // Always OK. 572 } 573 if call.Ellipsis.IsValid() { 574 return false // We just can't tell; there could be many more arguments. 575 } 576 if argNum < len(call.Args) { 577 return true 578 } 579 // There are bad indexes in the format or there are fewer arguments than the format needs. 580 // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". 581 arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed. 582 f.Badf(call.Pos(), `missing argument for %s("%s"): format reads arg %d, have only %d args`, state.name, state.format, arg, len(call.Args)-state.firstArg) 583 return false 584 } 585 586 // checkPrint checks a call to an unformatted print routine such as Println. 587 func (f *File) checkPrint(call *ast.CallExpr, name string) { 588 firstArg := 0 589 typ := f.pkg.types[call.Fun].Type 590 if typ == nil { 591 // Skip checking functions with unknown type. 592 return 593 } 594 if sig, ok := typ.(*types.Signature); ok { 595 if !sig.Variadic() { 596 // Skip checking non-variadic functions. 597 return 598 } 599 params := sig.Params() 600 firstArg = params.Len() - 1 601 602 typ := params.At(firstArg).Type() 603 typ = typ.(*types.Slice).Elem() 604 it, ok := typ.(*types.Interface) 605 if !ok || !it.Empty() { 606 // Skip variadic functions accepting non-interface{} args. 607 return 608 } 609 } 610 args := call.Args 611 if len(args) <= firstArg { 612 // Skip calls without variadic args. 613 return 614 } 615 args = args[firstArg:] 616 617 // check for Println(os.Stderr, ...) 618 if firstArg == 0 { 619 if sel, ok := args[0].(*ast.SelectorExpr); ok { 620 if x, ok := sel.X.(*ast.Ident); ok { 621 if x.Name == "os" && strings.HasPrefix(sel.Sel.Name, "Std") { 622 f.Badf(call.Pos(), "first argument to %s is %s.%s", name, x.Name, sel.Sel.Name) 623 } 624 } 625 } 626 } 627 arg := args[0] 628 if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { 629 if strings.Contains(lit.Value, "%") { 630 f.Badf(call.Pos(), "possible formatting directive in %s call", name) 631 } 632 } 633 if strings.HasSuffix(name, "ln") { 634 // The last item, if a string, should not have a newline. 635 arg = args[len(args)-1] 636 if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { 637 if strings.HasSuffix(lit.Value, `\n"`) { 638 f.Badf(call.Pos(), "%s call ends with newline", name) 639 } 640 } 641 } 642 for _, arg := range args { 643 if f.isFunctionValue(arg) { 644 f.Badf(call.Pos(), "arg %s in %s call is a function value, not a function call", f.gofmt(arg), name) 645 } 646 if f.recursiveStringer(arg) { 647 f.Badf(call.Pos(), "arg %s in %s call causes recursive call to String method", f.gofmt(arg), name) 648 } 649 } 650 }