aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-07-05 09:47:42 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-07-05 10:55:16 +0200
commit214e3e269cce39f25d2552d3ba994cced679d5e8 (patch)
treee8f0ed5aa35e286f87869d4efde8f01fec6bacc4 /tools
parent3940e7a64fa27c338ca1283b8f90143412b281ba (diff)
tools/syz-linter: check log/error text starting with capital letter
Update #1876
Diffstat (limited to 'tools')
-rw-r--r--tools/syz-linter/linter.go38
-rw-r--r--tools/syz-linter/testdata/src/lintertest/lintertest.go21
2 files changed, 57 insertions, 2 deletions
diff --git a/tools/syz-linter/linter.go b/tools/syz-linter/linter.go
index f154706cf..5d09debda 100644
--- a/tools/syz-linter/linter.go
+++ b/tools/syz-linter/linter.go
@@ -21,6 +21,7 @@ import (
"go/types"
"regexp"
"strings"
+ "unicode"
"golang.org/x/tools/go/analysis"
)
@@ -29,6 +30,10 @@ var AnalyzerPlugin analyzerPlugin
type analyzerPlugin struct{}
+func main() {
+ _ = AnalyzerPlugin
+}
+
func (*analyzerPlugin) GetAnalyzers() []*analysis.Analyzer {
return []*analysis.Analyzer{
SyzAnalyzer,
@@ -52,6 +57,8 @@ func run(pass *analysis.Pass) (interface{}, error) {
checkStringLenCompare(pass, n)
case *ast.FuncType:
checkFuncArgs(pass, n)
+ case *ast.CallExpr:
+ checkLogErrorFormat(pass, n)
}
return true
})
@@ -164,6 +171,33 @@ func reportFuncArgs(pass *analysis.Pass, fields []*ast.Field, first, last int) {
})
}
-func main() {
- _ = AnalyzerPlugin
+func checkLogErrorFormat(pass *analysis.Pass, n *ast.CallExpr) {
+ fun, ok := n.Fun.(*ast.SelectorExpr)
+ if !ok {
+ return
+ }
+ arg := 0
+ switch fmt.Sprintf("%v.%v", fun.X, fun.Sel) {
+ case "log.Print", "log.Printf", "log.Fatal", "log.Fatalf", "fmt.Error", "fmt.Errorf":
+ arg = 0
+ case "log.Logf":
+ arg = 1
+ default:
+ return
+ }
+ lit, ok := n.Args[arg].(*ast.BasicLit)
+ if !ok || lit.Kind != token.STRING {
+ return
+ }
+ val := lit.Value[1 : len(lit.Value)-1] // the value includes quotes
+ if len(val) < 2 || !unicode.IsUpper(rune(val[0])) || !unicode.IsLower(rune(val[1])) ||
+ publicIdentifier.MatchString(val) {
+ return
+ }
+ pass.Report(analysis.Diagnostic{
+ Pos: n.Pos(),
+ Message: "bad log/error",
+ })
}
+
+var publicIdentifier = regexp.MustCompile(`^[A-Z][[:alnum:]]+(\.[[:alnum:]]+)+ `)
diff --git a/tools/syz-linter/testdata/src/lintertest/lintertest.go b/tools/syz-linter/testdata/src/lintertest/lintertest.go
index 69b956e80..c44f61683 100644
--- a/tools/syz-linter/testdata/src/lintertest/lintertest.go
+++ b/tools/syz-linter/testdata/src/lintertest/lintertest.go
@@ -3,6 +3,11 @@
package lintertest
+import (
+ "fmt"
+ "log"
+)
+
/* some comment */ // want "Use C-style comments // instead of /* */"
var comment = 1 /* some comment */ // want "Use C-style comments // instead of /* */"
@@ -42,3 +47,19 @@ func funcArgsBad1() (a int, b int) { // want "Use 'a, b int'"
func funcArgsBad2(a int16, b, c uint32, d uint32, e int16) { // want "Use 'b, c, d uint32'"
}
+
+func logErrorMessages() {
+ fmt.Errorf("good message")
+ fmt.Errorf("good message %v", 0)
+ msg := "good message"
+ fmt.Errorf(msg)
+ log.Printf("good message")
+ log.Print("good message")
+ log.Print("Using.An.Identifier is ok as well")
+ log.Print(msg)
+
+ fmt.Errorf("Bad message") // want "bad log/error"
+ log.Fatalf("Bad message %v", 1) // want "bad log/error"
+ log.Printf("Bad message %v", 1) // want "bad log/error"
+ log.Print("Bad message") // want "bad log/error"
+}