Skip to content

Commit

Permalink
fix: disabling of rules using comments (#1284)
Browse files Browse the repository at this point in the history
* test: add test for disabled rules

* fix: disabling of rules with comments

* perf: use bitset for disabled rules

* perf: store transitive disabled rules

* test: improve test coverage
  • Loading branch information
didroe authored Sep 21, 2023
1 parent d100d99 commit a684dcc
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
low:
- rule:
cwe_ids:
- "319"
id: match_sink
title: ""
description: ""
documentation_url: ""
line_number: 7
full_filename: e2e/rules/testdata/data/disabled_rules/main.rb
filename: main.rb
source:
location:
start: 7
end: 7
column:
start: 3
end: 7
sink:
location:
start: 7
end: 7
column:
start: 3
end: 7
content: sink
parent_line_number: 7
snippet: sink
fingerprint: eb59f129d5424fb58e3bfcb5bfa83159_0
old_fingerprint: e94b7fee5e58e735f107aa1cb3cfb75b_0
code_extract: ' sink'


--

4 changes: 4 additions & 0 deletions e2e/rules/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func TestAuxilary(t *testing.T) {
runRulesTest("auxilary", "javascript_third_parties_datadog_test", t)
}

func TestDisabledRules(t *testing.T) {
runRulesTest("disabled_rules", "match_sink", t)
}

func TestReferenceFilters(t *testing.T) {
runRulesTest("reference_filters", "reference_filters_test", t)
}
Expand Down
8 changes: 8 additions & 0 deletions e2e/rules/testdata/data/disabled_rules/main.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# bearer:disable match_sink
def m
sink
end

def n
sink
end
9 changes: 9 additions & 0 deletions e2e/rules/testdata/rules/match_sink.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
patterns:
- sink
languages:
- ruby
severity: low
metadata:
cwe_id:
- 319
id: match_sink
175 changes: 175 additions & 0 deletions internal/scanner/ast/.snapshots/TestDisabledRules
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
([]ast_test.ruleInfo) (len=4) {
(ast_test.ruleInfo) {
ID: (string) (len=5) "rule1",
Index: (int) 5
},
(ast_test.ruleInfo) {
ID: (string) (len=5) "rule2",
Index: (int) 6
},
(ast_test.ruleInfo) {
ID: (string) (len=5) "rule3",
Index: (int) 7
},
(ast_test.ruleInfo) {
ID: (string) (len=5) "rule4",
Index: (int) 8
}
}
type: program
id: 0
range: 2:3 - 9:2
dataflow_sources:
- 1
- 2
- 3
children:
- type: comment
id: 1
range: 2:3 - 2:31
content: '# bearer:disable rule1,rule2'
- type: comment
id: 2
range: 3:3 - 3:25
content: '# bearer:disable rule3'
- type: method
id: 3
range: 4:3 - 8:6
disabledrules:
- 5
- 6
- 7
children:
- type: '"def"'
id: 4
range: 4:3 - 4:6
disabledrules:
- 5
- 6
- 7
- type: identifier
id: 5
range: 4:7 - 4:8
content: m
disabledrules:
- 5
- 6
- 7
- type: method_parameters
id: 6
range: 4:8 - 4:11
dataflow_sources:
- 7
- 8
- 9
disabledrules:
- 5
- 6
- 7
children:
- type: '"("'
id: 7
range: 4:8 - 4:9
disabledrules:
- 5
- 6
- 7
- type: identifier
id: 8
range: 4:9 - 4:10
content: a
disabledrules:
- 5
- 6
- 7
- type: '")"'
id: 9
range: 4:10 - 4:11
disabledrules:
- 5
- 6
- 7
- type: comment
id: 10
range: 5:4 - 5:26
content: '# bearer:disable rule4'
disabledrules:
- 5
- 6
- 7
- type: call
id: 11
range: 6:4 - 6:9
disabledrules:
- 5
- 6
- 7
- 8
children:
- type: identifier
id: 12
range: 6:4 - 6:5
content: a
alias_of:
- 8
disabledrules:
- 5
- 6
- 7
- 8
- type: '"."'
id: 13
range: 6:5 - 6:6
disabledrules:
- 5
- 6
- 7
- 8
- type: identifier
id: 14
range: 6:6 - 6:9
content: foo
disabledrules:
- 5
- 6
- 7
- 8
- type: call
id: 15
range: 7:4 - 7:9
disabledrules:
- 5
- 6
- 7
children:
- type: identifier
id: 16
range: 7:4 - 7:5
content: b
disabledrules:
- 5
- 6
- 7
- type: '"."'
id: 17
range: 7:5 - 7:6
disabledrules:
- 5
- 6
- 7
- type: identifier
id: 18
range: 7:6 - 7:9
content: bar
disabledrules:
- 5
- 6
- 7
- type: '"end"'
id: 19
range: 8:3 - 8:6
disabledrules:
- 5
- 6
- 7

9 changes: 5 additions & 4 deletions internal/scanner/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func Parse(
language language.Language,
contentBytes []byte,
) (*tree.Tree, error) {
builder, err := parseBuilder(ctx, language, contentBytes)
builder, err := parseBuilder(ctx, language, contentBytes, 0)
if err != nil {
return nil, err
}
Expand All @@ -35,7 +35,7 @@ func ParseAndAnalyze(
querySet *query.Set,
contentBytes []byte,
) (*tree.Tree, error) {
builder, err := parseBuilder(ctx, language, contentBytes)
builder, err := parseBuilder(ctx, language, contentBytes, len(ruleSet.Rules()))
if err != nil {
return nil, err
}
Expand All @@ -56,6 +56,7 @@ func parseBuilder(
ctx context.Context,
language language.Language,
contentBytes []byte,
ruleCount int,
) (*tree.Builder, error) {
parser := sitter.NewParser()
defer parser.Close()
Expand All @@ -67,7 +68,7 @@ func parseBuilder(
return nil, err
}

return tree.NewBuilder(contentBytes, sitterTree.RootNode()), nil
return tree.NewBuilder(contentBytes, sitterTree.RootNode(), ruleCount), nil
}

func analyzeNode(
Expand All @@ -91,7 +92,7 @@ func analyzeNode(
continue
}

disabledRules = addDisabledRules(ruleSet, builder, disabledRules, node)
disabledRules = addDisabledRules(ruleSet, builder, disabledRules, child)
if err := analyzeNode(ctx, ruleSet, builder, analyzer, child); err != nil {
return err
}
Expand Down
77 changes: 77 additions & 0 deletions internal/scanner/ast/ast_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ast_test

import (
"context"
"testing"

"github.com/bradleyjkemp/cupaloy"

"github.com/bearer/bearer/internal/commands/process/settings"
"github.com/bearer/bearer/internal/languages/ruby"
"github.com/bearer/bearer/internal/scanner/ast"
"github.com/bearer/bearer/internal/scanner/ast/query"
"github.com/bearer/bearer/internal/scanner/ruleset"
)

type ruleInfo struct {
ID string
Index int
}

func TestDisabledRules(t *testing.T) {
content := `
# bearer:disable rule1,rule2
# bearer:disable rule3
def m(a)
# bearer:disable rule4
a.foo
b.bar
end
`

language := ruby.Get()
languageIDs := []string{language.ID()}

ruleSet, err := ruleset.New(
language.ID(),
map[string]*settings.Rule{
"rule1": {Id: "rule1", Languages: languageIDs},
"rule2": {Id: "rule2", Languages: languageIDs},
"rule3": {Id: "rule3", Languages: languageIDs},
"rule4": {Id: "rule4", Languages: languageIDs},
},
)
if err != nil {
t.Fatalf("failed to create rule set: %s", err)
}

var ruleDump []ruleInfo
for _, rule := range ruleSet.Rules() {
if rule.Type() != ruleset.RuleTypeBuiltin {
ruleDump = append(ruleDump, ruleInfo{ID: rule.ID(), Index: rule.Index()})
}
}

querySet := query.NewSet(language.ID(), language.SitterLanguage())
if err := querySet.Compile(); err != nil {
t.Fatalf("failed to compile query set: %s", err)
}

tree, err := ast.ParseAndAnalyze(
context.Background(),
language,
ruleSet,
querySet,
[]byte(content),
)

if err != nil {
t.Fatalf("failed to parse and analyze input: %s", err)
}

cupaloy.SnapshotT(
t,
ruleDump,
tree.RootNode().Dump(),
)
}
Loading

0 comments on commit a684dcc

Please sign in to comment.