From 87c3c1b0020280fe216933501c96a913eaaafb2b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 31 Jan 2013 07:53:38 -0800 Subject: [PATCH] cmd/vet: handle added string constants in printf format check Fixes #4599. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/7226067 --- src/cmd/vet/print.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go index a402d3de41..ea85edac1d 100644 --- a/src/cmd/vet/print.go +++ b/src/cmd/vet/print.go @@ -11,6 +11,7 @@ import ( "fmt" "go/ast" "go/token" + "strconv" "strings" "unicode/utf8" ) @@ -62,6 +63,23 @@ func (f *File) literal(value ast.Expr) *ast.BasicLit { switch v := value.(type) { case *ast.BasicLit: return v + case *ast.ParenExpr: + return f.literal(v.X) + case *ast.BinaryExpr: + if v.Op != token.ADD { + break + } + litX := f.literal(v.X) + litY := f.literal(v.Y) + if litX != nil && litY != nil { + lit := *litX + x, errX := strconv.Unquote(litX.Value) + y, errY := strconv.Unquote(litY.Value) + if errX == nil && errY == nil { + lit.Value = strconv.Quote(x + y) + return &lit + } + } case *ast.Ident: // See if it's a constant or initial value (we can't tell the difference). if v.Obj == nil || v.Obj.Decl == nil { @@ -101,7 +119,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string, skip int) { if lit.Kind != token.STRING { f.Badf(call.Pos(), "literal %v not a string in call to", lit.Value, name) } - format := lit.Value + format, err := strconv.Unquote(lit.Value) + if err != nil { + f.Badf(call.Pos(), "invalid quoted string literal") + } if !strings.Contains(format, "%") { if len(call.Args) > skip+1 { f.Badf(call.Pos(), "no formatting directive in %s call", name) @@ -282,6 +303,7 @@ func BadFunctionUsedInTests() { fmt.Println() // not an error fmt.Println("%s", "hi") // ERROR "possible formatting directive in Println call" fmt.Printf("%s", "hi", 3) // ERROR "wrong number of args in Printf call" + fmt.Printf("%"+("s"), "hi", 3) // ERROR "wrong number of args in Printf call" fmt.Printf("%s%%%d", "hi", 3) // correct fmt.Printf("%08s", "woo") // correct fmt.Printf("% 8s", "woo") // correct