1
0
mirror of https://github.com/golang/go synced 2024-11-24 04:00:13 -07:00

cmd/vet: if a function modifies its args, it's not a print wrapper

Fixes #26486
Updates #26555

Change-Id: I402137b796e574e9b085ab54290d1b4ef73d3fcc
Reviewed-on: https://go-review.googlesource.com/125039
Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
Ian Lance Taylor 2018-07-19 14:35:02 -07:00
parent 214f7ec554
commit 240ae7e304
2 changed files with 44 additions and 6 deletions

View File

@ -68,12 +68,12 @@ type printfExport struct {
var printfImported = make(map[string]map[string]int) var printfImported = make(map[string]map[string]int)
type printfWrapper struct { type printfWrapper struct {
name string name string
fn *ast.FuncDecl fn *ast.FuncDecl
format *ast.Field format *ast.Field
args *ast.Field args *ast.Field
callers []printfCaller callers []printfCaller
printfLike bool failed bool // if true, not a printf wrapper
} }
type printfCaller struct { type printfCaller struct {
@ -168,6 +168,33 @@ func findPrintfLike(pkg *Package) {
for _, w := range wrappers { for _, w := range wrappers {
// Scan function for calls that could be to other printf-like functions. // Scan function for calls that could be to other printf-like functions.
ast.Inspect(w.fn.Body, func(n ast.Node) bool { ast.Inspect(w.fn.Body, func(n ast.Node) bool {
if w.failed {
return false
}
// TODO: Relax these checks; issue 26555.
if assign, ok := n.(*ast.AssignStmt); ok {
for _, lhs := range assign.Lhs {
if match(lhs, w.format) || match(lhs, w.args) {
// Modifies the format
// string or args in
// some way, so not a
// simple wrapper.
w.failed = true
return false
}
}
}
if un, ok := n.(*ast.UnaryExpr); ok && un.Op == token.AND {
if match(un.X, w.format) || match(un.X, w.args) {
// Taking the address of the
// format string or args,
// so not a simple wrapper.
w.failed = true
return false
}
}
call, ok := n.(*ast.CallExpr) call, ok := n.(*ast.CallExpr)
if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) { if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) {
return true return true

View File

@ -318,6 +318,9 @@ func PrintfTests() {
l.Print("%d", 1) // ERROR "Print call has possible formatting directive %d" l.Print("%d", 1) // ERROR "Print call has possible formatting directive %d"
l.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string" l.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string"
l.Println("%d", 1) // ERROR "Println call has possible formatting directive %d" l.Println("%d", 1) // ERROR "Println call has possible formatting directive %d"
// Issue 26486
dbg("", 1) // no error "call has arguments but no formatting directive"
} }
func someString() string { return "X" } func someString() string { return "X" }
@ -650,3 +653,11 @@ func UnexportedStringerOrError() {
func DisableErrorForFlag0() { func DisableErrorForFlag0() {
fmt.Printf("%0t", true) fmt.Printf("%0t", true)
} }
// Issue 26486.
func dbg(format string, args ...interface{}) {
if format == "" {
format = "%v"
}
fmt.Printf(format, args...)
}