Skip to content

Commit

Permalink
fix: java and javascript since php changes (#1300)
Browse files Browse the repository at this point in the history
* fix(java): add missing pattern container types

* fix(javascript): match strings correctly
  • Loading branch information
didroe authored Oct 3, 2023
1 parent 6f6e6b9 commit d4bfbfe
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
(*builder.Result)({
Query: (string) (len=328) "([(class_declaration . (_) . [(class_body [(method_declaration . [ (void_type )] @param1 . [ (identifier )] @param2 . [ (formal_parameters )] . [(block [(try_statement [ (block )] [(catch_clause . [(catch_formal_parameter . [(catch_type (_) @match)] . [ (identifier )] @param3 .)] . [ (block )] .)])] )] .)] )] .)] @root)",
VariableNames: ([]string) (len=1) {
(string) (len=1) "_"
},
ParamToVariable: (map[string]string) {
},
EqualParams: ([][]string) <nil>,
ParamToContent: (map[string]map[string]string) (len=3) {
(string) (len=6) "param1": (map[string]string) (len=1) {
(string) (len=9) "void_type": (string) (len=4) "void"
},
(string) (len=6) "param2": (map[string]string) (len=1) {
(string) (len=10) "identifier": (string) (len=4) "main"
},
(string) (len=6) "param3": (map[string]string) (len=1) {
(string) (len=10) "identifier": (string) (len=1) "e"
}
},
RootVariable: (*language.PatternVariable)(<nil>)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
(*builder.Result)({
Query: (string) (len=190) "([(class_declaration . (_) . [(class_body [(method_declaration . [ (void_type )] @param1 . [ (identifier )] @param2 . [(formal_parameters . (_) @match . )] . [ (block )] .)] )] .)] @root)",
VariableNames: ([]string) (len=1) {
(string) (len=1) "_"
},
ParamToVariable: (map[string]string) {
},
EqualParams: ([][]string) <nil>,
ParamToContent: (map[string]map[string]string) (len=2) {
(string) (len=6) "param1": (map[string]string) (len=1) {
(string) (len=9) "void_type": (string) (len=4) "void"
},
(string) (len=6) "param2": (map[string]string) (len=1) {
(string) (len=10) "identifier": (string) (len=4) "main"
}
},
RootVariable: (*language.PatternVariable)(<nil>)
})
29 changes: 29 additions & 0 deletions internal/languages/java/java_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
_ "embed"
"testing"

"github.com/bearer/bearer/internal/languages/java"
"github.com/bearer/bearer/internal/languages/testhelper"
patternquerybuilder "github.com/bearer/bearer/internal/scanner/detectors/customrule/patternquery/builder"
"github.com/bradleyjkemp/cupaloy"
)

//go:embed testdata/logger.yml
Expand All @@ -20,3 +23,29 @@ func TestFlow(t *testing.T) {
func TestScope(t *testing.T) {
testhelper.GetRunner(t, scopeRule, "Java").RunTest(t, "./testdata/scope", ".snapshots/")
}

func TestPattern(t *testing.T) {
for _, test := range []struct{ name, pattern string }{
{"method params is a container type", `
class $<_> {
void main($<!>$<_>) {}
}
`},
{"catch types is a container type", `
class $<_> {
void main() {
try {} catch ($<!>$<_> e) {}
}
}
`},
} {
t.Run(test.name, func(tt *testing.T) {
result, err := patternquerybuilder.Build(java.Get(), test.pattern, "")
if err != nil {
tt.Fatalf("failed to build pattern: %s", err)
}

cupaloy.SnapshotT(tt, result)
})
}
}
22 changes: 14 additions & 8 deletions internal/languages/java/pattern/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,35 @@ import (

var (
// $<name:type> or $<name:type1|type2> or $<name>
patternQueryVariableRegex = regexp.MustCompile(`\$<(?P<name>[^>:!\.]+)(?::(?P<types>[^>]+))?>`)
matchNodeRegex = regexp.MustCompile(`\$<!>`)
ellipsisRegex = regexp.MustCompile(`\$<\.\.\.>`)
queryVariableRegex = regexp.MustCompile(`\$<(?P<name>[^>:!\.]+)(?::(?P<types>[^>]+))?>`)
matchNodeRegex = regexp.MustCompile(`\$<!>`)
ellipsisRegex = regexp.MustCompile(`\$<\.\.\.>`)

matchNodeContainerTypes = []string{"catch_formal_parameter", "catch_type", "formal_parameters"}

// todo: see if it is ok to replace typescripts `member_expression` with javas `field_access` and `method_invocation`
allowedPatternQueryTypes = []string{"identifier", "type_identifier", "_", "field_access", "method_invocation", "string_literal"}
allowedQueryTypes = []string{"identifier", "type_identifier", "_", "field_access", "method_invocation", "string_literal"}
)

type Pattern struct {
language.PatternBase
}

func (*Pattern) ExtractVariables(input string) (string, []language.PatternVariable, error) {
nameIndex := patternQueryVariableRegex.SubexpIndex("name")
typesIndex := patternQueryVariableRegex.SubexpIndex("types")
nameIndex := queryVariableRegex.SubexpIndex("name")
typesIndex := queryVariableRegex.SubexpIndex("types")
i := 0

var params []language.PatternVariable

replaced, err := regex.ReplaceAllWithSubmatches(patternQueryVariableRegex, input, func(submatches []string) (string, error) {
replaced, err := regex.ReplaceAllWithSubmatches(queryVariableRegex, input, func(submatches []string) (string, error) {
nodeTypes := strings.Split(submatches[typesIndex], "|")
if nodeTypes[0] == "" {
nodeTypes = []string{"_"}
}

for _, nodeType := range nodeTypes {
if !slices.Contains(allowedPatternQueryTypes, nodeType) {
if !slices.Contains(allowedQueryTypes, nodeType) {
return "", fmt.Errorf("invalid node type '%s' in pattern query", nodeType)
}
}
Expand Down Expand Up @@ -128,3 +130,7 @@ func (*Pattern) NodeTypes(node *tree.Node) []string {

return []string{node.Type()}
}

func (*Pattern) ContainerTypes() []string {
return matchNodeContainerTypes
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,19 @@ children:
data:
value: c
isliteral: true
- node: 8
content: a
data:
value: a
isliteral: true
- node: 16
content: b
data:
value: b
isliteral: true
- node: 35
content: c
data:
value: c
isliteral: true

Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
type: program
id: 0
range: 1:1 - 7:1
range: 1:1 - 9:1
dataflow_sources:
- 1
- 6
- 17
- 25
- 33
children:
- type: expression_statement
id: 1
Expand Down Expand Up @@ -155,6 +156,43 @@ children:
- type: '"`"'
id: 32
range: 6:8 - 6:9
- type: expression_statement
id: 33
range: 8:1 - 8:19
children:
- type: string
id: 34
range: 8:1 - 8:19
dataflow_sources:
- 35
- 36
- 37
- 38
- 39
- 40
children:
- type: '"""'
id: 35
range: 8:1 - 8:2
- type: string_fragment
id: 36
range: 8:2 - 8:7
content: hello
- type: escape_sequence
id: 37
range: 8:7 - 8:11
content: \x20
- type: string_fragment
id: 38
range: 8:11 - 8:16
content: world
- type: escape_sequence
id: 39
range: 8:16 - 8:18
content: \\
- type: '"""'
id: 40
range: 8:18 - 8:19

- node: 2
content: '"ab"'
Expand All @@ -171,6 +209,16 @@ children:
data:
value: a b
isliteral: true
- node: 34
content: '"hello\x20world\\"'
data:
value: hello world\
isliteral: true
- node: 4
content: ab
data:
value: ab
isliteral: true
- node: 8
content: '"a"'
data:
Expand All @@ -186,4 +234,39 @@ children:
data:
value: a
isliteral: true
- node: 36
content: hello
data:
value: hello
isliteral: true
- node: 37
content: \x20
data:
value: ' '
isliteral: true
- node: 38
content: world
data:
value: world
isliteral: true
- node: 39
content: \\
data:
value: \
isliteral: true
- node: 10
content: a
data:
value: a
isliteral: true
- node: 15
content: b
data:
value: b
isliteral: true
- node: 23
content: a
data:
value: a
isliteral: true

Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,9 @@ children:
data:
value: a
isliteral: true
- node: 5
content: a
data:
value: a
isliteral: true

18 changes: 16 additions & 2 deletions internal/languages/javascript/detectors/string/string.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package string

import (
"fmt"
"strconv"

"github.com/bearer/bearer/internal/scanner/ast/query"
"github.com/bearer/bearer/internal/scanner/ast/tree"
"github.com/bearer/bearer/internal/scanner/ruleset"
"github.com/bearer/bearer/internal/util/stringutil"

"github.com/bearer/bearer/internal/scanner/detectors/common"
"github.com/bearer/bearer/internal/scanner/detectors/types"
Expand All @@ -28,8 +30,20 @@ func (detector *stringDetector) DetectAt(
) ([]interface{}, error) {
switch node.Type() {
case "string":
return common.ConcatenateChildStrings(node, detectorContext)
case "string_fragment":
return []interface{}{common.String{
Value: node.Content(),
IsLiteral: true,
}}, nil
case "escape_sequence":
value, err := strconv.Unquote(fmt.Sprintf(`"%s"`, node.Content()))
if err != nil {
return nil, fmt.Errorf("failed to decode escape sequence: %w", err)
}

return []interface{}{common.String{
Value: stringutil.StripQuotes(node.Content()),
Value: value,
IsLiteral: true,
}}, nil
case "template_string":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@

x = "a"
`${x} b`

"hello\x20world\\"
4 changes: 0 additions & 4 deletions internal/languages/javascript/pattern/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ type Pattern struct {
language.PatternBase
}

func (*Pattern) IsLeaf(node *tree.Node) bool {
return node.Type() == "string"
}

func (*Pattern) ExtractVariables(input string) (string, []language.PatternVariable, error) {
nameIndex := patternQueryVariableRegex.SubexpIndex("name")
typesIndex := patternQueryVariableRegex.SubexpIndex("types")
Expand Down

0 comments on commit d4bfbfe

Please sign in to comment.