-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
9b1c400
commit 4988b58
Showing
15 changed files
with
680 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package ast | ||
|
||
import ( | ||
"github.com/sourcegraph/go-lsp" | ||
) | ||
|
||
type Node struct { | ||
Line int | ||
StartChar int | ||
EndChar int | ||
DocOffset int64 | ||
Parent *Node | ||
Children []*Node | ||
Name string | ||
Value string | ||
Attributes map[string]string | ||
} | ||
|
||
type Tree struct { | ||
Root *Node | ||
Document lsp.DocumentURI | ||
} | ||
|
||
type Parser interface { | ||
Parse(content []byte, uri lsp.DocumentURI) Tree | ||
} | ||
|
||
type Visitor interface { | ||
visit(*Node) | ||
} | ||
|
||
func (n *Node) Accept(v Visitor) { | ||
v.visit(n) | ||
} | ||
|
||
func (n *Node) Add(child *Node) *Node { | ||
n.Children = append(n.Children, child) | ||
child.Parent = n | ||
return n | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package ast | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNodeAddChild(t *testing.T) { | ||
var node = Node{} | ||
var child = Node{} | ||
node.Add(&child) | ||
assert.NotNil(t, node.Children) | ||
assert.Equal(t, &node, child.Parent) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package maven | ||
|
||
import ( | ||
"encoding/xml" | ||
"io" | ||
"strings" | ||
|
||
"github.com/rs/zerolog/log" | ||
"github.com/sourcegraph/go-lsp" | ||
|
||
"github.com/snyk/snyk-ls/ast" | ||
) | ||
|
||
type Parser struct { | ||
tree ast.Tree | ||
} | ||
|
||
type dependency struct { | ||
Group string `xml:"group"` | ||
ArtifactId string `xml:"artifactId"` | ||
Version string `xml:"version"` | ||
Scope string `xml:"scope"` | ||
} | ||
|
||
func (p *Parser) Parse(content string, uri lsp.DocumentURI) ast.Tree { | ||
tree := p.initTree(uri, content) | ||
d := xml.NewDecoder(strings.NewReader(content)) | ||
var offset int64 | ||
for { | ||
token, err := d.Token() | ||
offset = d.InputOffset() | ||
if token == nil || err == io.EOF { | ||
// EOF means we're done. | ||
break | ||
} else if err != nil { | ||
log.Err(err).Msg("Couldn't parse XML") | ||
} | ||
|
||
switch xmlType := token.(type) { | ||
|
||
case xml.StartElement: | ||
if xmlType.Name.Local == "dependency" { | ||
var dep dependency | ||
if err = d.DecodeElement(&dep, &xmlType); err != nil { | ||
log.Err(err).Msg("Couldn't decode dependency") | ||
} | ||
offsetAfter := d.InputOffset() | ||
node := p.addNewNodeTo(tree.Root, offset, offsetAfter, dep) | ||
log.Debug().Interface("node", node).Str("uri", string(p.tree.Document)).Msg("Added dependency node") | ||
} | ||
default: | ||
} | ||
} | ||
return tree | ||
} | ||
|
||
func (p *Parser) initTree(uri lsp.DocumentURI, content string) ast.Tree { | ||
var currentLine = 0 | ||
root := ast.Node{ | ||
Line: currentLine, | ||
StartChar: 0, | ||
EndChar: -1, | ||
DocOffset: 0, | ||
Parent: nil, | ||
Children: nil, | ||
Name: string(uri), | ||
Value: content, | ||
} | ||
p.tree = ast.Tree{ | ||
Root: &root, | ||
Document: uri, | ||
} | ||
return p.tree | ||
} | ||
|
||
func (p *Parser) addNewNodeTo(parent *ast.Node, offsetBefore int64, offsetAfter int64, dep dependency) *ast.Node { | ||
content := p.tree.Root.Value | ||
contentInclusive := content[0:offsetAfter] | ||
startTag := "<version>" | ||
endTag := "</version" | ||
versionStartOffset := strings.LastIndex(contentInclusive, startTag) | ||
contentUntilVersion := content[0:versionStartOffset] | ||
line := strings.Count(contentUntilVersion, "\n") | ||
lineStartOffset := strings.LastIndex(contentUntilVersion, "\n") | ||
versionValueStartOffset := versionStartOffset + len(startTag) - lineStartOffset - 1 | ||
versionValueEndOffset := strings.LastIndex(contentInclusive, endTag) - lineStartOffset - 1 | ||
|
||
node := ast.Node{ | ||
Line: line, | ||
StartChar: versionValueStartOffset, | ||
EndChar: versionValueEndOffset, | ||
DocOffset: offsetBefore, | ||
Parent: parent, | ||
Children: nil, | ||
Name: dep.ArtifactId, | ||
Value: dep.Version, | ||
Attributes: make(map[string]string), | ||
} | ||
parent.Add(&node) | ||
return &node | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package maven | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/sourcegraph/go-lsp" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCreateDependencyTree(t *testing.T) { | ||
var testPath, _ = filepath.Abs("testdata/pom.xml") | ||
var testContent, _ = os.ReadFile(testPath) | ||
doc := lsp.DocumentURI(testPath) | ||
parser := Parser{} | ||
tree := parser.Parse(string(testContent), doc) | ||
children := tree.Root.Children | ||
assert.Len(t, children, 2, "Should have extracted 2 deps from pom.xml") | ||
|
||
assert.Equal(t, 38, children[0].Line) | ||
assert.Equal(t, 15, children[0].StartChar) | ||
assert.Equal(t, 21, children[0].EndChar) | ||
|
||
assert.Equal(t, 43, children[1].Line) | ||
assert.Equal(t, 15, children[1].StartChar) | ||
assert.Equal(t, 21, children[1].EndChar) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>io.snyk</groupId> | ||
<artifactId>maven-goof</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<source>14</source> | ||
<target>14</target> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<properties> | ||
<maven.compiler.source>15</maven.compiler.source> | ||
<maven.compiler.target>15</maven.compiler.target> | ||
</properties> | ||
|
||
<dependencies> | ||
<!-- <dependency>--> | ||
<!-- <!– log4shell–>--> | ||
<!-- <groupId>org.apache.logging.log4j</groupId>--> | ||
<!-- <artifactId>log4j-core</artifactId>--> | ||
<!-- <version>2.14.1</version>--> | ||
<!-- </dependency>--> | ||
<dependency> | ||
<!-- log4shell--> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-core</artifactId> | ||
<version>2.14.1</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.logging.log4j</groupId> | ||
<artifactId>log4j-api</artifactId> | ||
<version>2.14.1</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package oss | ||
|
||
import ( | ||
"github.com/rs/zerolog/log" | ||
"github.com/sourcegraph/go-lsp" | ||
|
||
"github.com/snyk/snyk-ls/ast/maven" | ||
) | ||
|
||
type MavenRangeFinder struct { | ||
doc lsp.TextDocumentItem | ||
} | ||
|
||
func (m *MavenRangeFinder) Find(issue ossIssue) lsp.Range { | ||
searchPackage, version := introducingPackageAndVersion(issue) | ||
log.Debug().Interface("issue", issue).Str("searchPackage", searchPackage).Str("searchVersion", version) | ||
parser := maven.Parser{} | ||
tree := parser.Parse(m.doc.Text, m.doc.URI) | ||
for _, depNode := range tree.Root.Children { | ||
if searchPackage == depNode.Name { | ||
log.Debug().Interface("dependency", depNode).Str("issueId", issue.Id).Msg("Found dependency for issue") | ||
return lsp.Range{ | ||
Start: lsp.Position{Line: depNode.Line, Character: depNode.StartChar}, | ||
End: lsp.Position{Line: depNode.Line, Character: depNode.EndChar}, | ||
} | ||
} | ||
} | ||
return lsp.Range{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package oss | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/sourcegraph/go-lsp" | ||
"github.com/stretchr/testify/assert" | ||
|
||
"github.com/snyk/snyk-ls/config/environment" | ||
) | ||
|
||
func TestMavenRangeFinder_Find(t *testing.T) { | ||
environment.Load() | ||
environment.Format = environment.FormatHtml | ||
|
||
var issue = ossIssue{ | ||
Id: "testIssue", | ||
Name: "SNYK-TEST-ISSUE-1", | ||
Title: "THOU SHALL NOT PASS", | ||
Severity: "1", | ||
LineNumber: 0, | ||
Description: "Getting into Moria is an issue!", | ||
References: nil, | ||
Version: "", | ||
PackageManager: "maven", | ||
From: []string{"[email protected]", "org.apache.logging.log4j:[email protected]"}, | ||
} | ||
var testPath, _ = filepath.Abs("testdata/pom.xml") | ||
var testContent, _ = os.ReadFile(testPath) | ||
var doc = lsp.TextDocumentItem{ | ||
URI: lsp.DocumentURI(testPath), | ||
LanguageID: "xml", | ||
Version: 0, | ||
Text: string(testContent), | ||
} | ||
|
||
expectedRange := lsp.Range{ | ||
Start: lsp.Position{ | ||
Line: 38, | ||
Character: 15, | ||
}, | ||
End: lsp.Position{ | ||
Line: 38, | ||
Character: 21, | ||
}, | ||
} | ||
|
||
actualRange := findRange(issue, doc) | ||
assert.Equal(t, expectedRange, actualRange) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package oss | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/rs/zerolog/log" | ||
"github.com/sourcegraph/go-lsp" | ||
) | ||
|
||
type NpmRangeFinder struct { | ||
doc lsp.TextDocumentItem | ||
myRange lsp.Range | ||
} | ||
|
||
func (n *NpmRangeFinder) Find(issue ossIssue) lsp.Range { | ||
searchPackage, _ := introducingPackageAndVersion(issue) | ||
var lines = strings.Split(strings.ReplaceAll(n.doc.Text, "\r\n", "\n"), "\n") | ||
var start lsp.Position | ||
var end lsp.Position | ||
for i := 0; i < len(lines); i++ { | ||
line := lines[i] | ||
log.Trace().Interface("issueId", issue.Id).Str("line", line).Msg("scanning line for " + searchPackage) | ||
elems := strings.Split(line, ":") | ||
if len(elems) > 1 { | ||
jsonKey := strings.Trim(strings.Trim(elems[0], " "), "\"") | ||
if jsonKey == searchPackage { | ||
start.Line = i | ||
start.Character = strings.Index(line, searchPackage) - 1 | ||
end.Line = i | ||
end.Character = len(strings.ReplaceAll(line, ",", "")) | ||
log.Debug().Str("issueId", issue.Id).Interface("start", start).Interface("end", end).Msg("found range for " + searchPackage) | ||
break | ||
} | ||
} | ||
} | ||
n.myRange = lsp.Range{ | ||
Start: start, | ||
End: end, | ||
} | ||
return n.myRange | ||
} |
Oops, something went wrong.