From 4538cb2a0fd5238c7a2603f508ac7f0a6e692a31 Mon Sep 17 00:00:00 2001 From: "Iskander (Alex) Sharipov" Date: Mon, 3 Jan 2022 14:11:54 +0300 Subject: [PATCH] ruleguard: pass imports table to gogrep pattern compiler (#343) This avoids any miscompiled patterns as well as allows more precise matching of package symbols in function call contexts. --- analyzer/analyzer_test.go | 1 + analyzer/testdata/src/imports/f1.go | 27 ++++++++++++++++++++++++++ analyzer/testdata/src/imports/rules.go | 17 ++++++++++++++++ go.mod | 2 +- go.sum | 4 ++++ ruleguard/ir_loader.go | 17 ++++++++++++---- 6 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 analyzer/testdata/src/imports/f1.go create mode 100644 analyzer/testdata/src/imports/rules.go diff --git a/analyzer/analyzer_test.go b/analyzer/analyzer_test.go index 28896263..c721961b 100644 --- a/analyzer/analyzer_test.go +++ b/analyzer/analyzer_test.go @@ -45,6 +45,7 @@ var tests = []struct { {name: "uber"}, {name: "localfunc"}, {name: "goversion", flags: map[string]string{"go": "1.16"}}, + {name: "imports"}, } func TestDirectiveComments(t *testing.T) { diff --git a/analyzer/testdata/src/imports/f1.go b/analyzer/testdata/src/imports/f1.go new file mode 100644 index 00000000..5cc27fa4 --- /dev/null +++ b/analyzer/testdata/src/imports/f1.go @@ -0,0 +1,27 @@ +package imports + +import ( + crand "crypto/rand" + "math/rand" +) + +func _() { + _, _ = crand.Read(nil) // want `\Qcrypto/rand` + _, _ = rand.Read(nil) // want `\Qmath/rand` +} + +func _() { + _, _ = rand.Read(nil) // want `\Qmath/rand` + _, _ = crand.Read(nil) // want `\Qcrypto/rand` +} + +func _() { + var rand distraction + _, _ = rand.Read(nil) +} + +type distraction struct{} + +func (distraction) Read(p []byte) (int, error) { + return 0, nil +} diff --git a/analyzer/testdata/src/imports/rules.go b/analyzer/testdata/src/imports/rules.go new file mode 100644 index 00000000..566b3cec --- /dev/null +++ b/analyzer/testdata/src/imports/rules.go @@ -0,0 +1,17 @@ +//go:build ignore +// +build ignore + +package gorules + +import ( + "github.com/quasilyte/go-ruleguard/dsl" +) + +func testMathRand(m dsl.Matcher) { + m.Match(`rand.Read($*_)`).Report(`math/rand`) +} + +func testCryptoRand(m dsl.Matcher) { + m.Import(`crypto/rand`) + m.Match(`rand.Read($*_)`).Report(`crypto/rand`) +} diff --git a/go.mod b/go.mod index b61d1cf2..710f2830 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,6 @@ require ( github.com/google/go-cmp v0.5.6 github.com/quasilyte/go-ruleguard/dsl v0.3.12-0.20220101150716-969a394a9451 github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71 - github.com/quasilyte/gogrep v0.0.0-20211226113550-e12a97c7d96d + github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 golang.org/x/tools v0.0.0-20201230224404-63754364767c ) diff --git a/go.sum b/go.sum index 506a46ff..f6ae17b2 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,10 @@ github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71 h1:CN github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/gogrep v0.0.0-20211226113550-e12a97c7d96d h1:HUyLC9v8wzT8PBFdZjGehLLNSPzQMXDsbREsMHxwma8= github.com/quasilyte/gogrep v0.0.0-20211226113550-e12a97c7d96d/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/gogrep v0.0.0-20220103102714-b302ec19c4fe h1:4QqQfYkJRjKR94aebELDiHFj/f+5lFKtQTVOt7luT20= +github.com/quasilyte/gogrep v0.0.0-20220103102714-b302ec19c4fe/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 h1:P4QPNn+TK49zJjXKERt/vyPbv/mCHB/zQ4flDYOMN+M= +github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/ruleguard/ir_loader.go b/ruleguard/ir_loader.go index 03e75000..7e29c81b 100644 --- a/ruleguard/ir_loader.go +++ b/ruleguard/ir_loader.go @@ -253,7 +253,7 @@ func (l *irLoader) loadRuleGroup(group *ir.RuleGroup) error { } for _, rule := range group.Rules { - if err := l.loadRule(rule); err != nil { + if err := l.loadRule(group, rule); err != nil { return err } } @@ -261,7 +261,7 @@ func (l *irLoader) loadRuleGroup(group *ir.RuleGroup) error { return nil } -func (l *irLoader) loadRule(rule ir.Rule) error { +func (l *irLoader) loadRule(group *ir.RuleGroup, rule ir.Rule) error { proto := goRule{ line: rule.Line, group: l.group, @@ -282,7 +282,7 @@ func (l *irLoader) loadRule(rule ir.Rule) error { } for _, pat := range rule.SyntaxPatterns { - if err := l.loadSyntaxRule(proto, info, rule, pat.Value, pat.Line); err != nil { + if err := l.loadSyntaxRule(group, proto, info, rule, pat.Value, pat.Line); err != nil { return err } } @@ -312,15 +312,24 @@ func (l *irLoader) loadCommentRule(resultProto goRule, rule ir.Rule, src string, return nil } -func (l *irLoader) loadSyntaxRule(resultProto goRule, filterInfo filterInfo, rule ir.Rule, src string, line int) error { +func (l *irLoader) loadSyntaxRule(group *ir.RuleGroup, resultProto goRule, filterInfo filterInfo, rule ir.Rule, src string, line int) error { result := resultProto result.line = line + var imports map[string]string + if len(group.Imports) != 0 { + imports = make(map[string]string) + for _, imported := range group.Imports { + imports[imported.Name] = imported.Path + } + } + gogrepConfig := gogrep.CompileConfig{ Fset: l.gogrepFset, Src: src, Strict: false, WithTypes: true, + Imports: imports, } pat, info, err := gogrep.Compile(gogrepConfig) if err != nil {