internal/lsp/command: add VulncheckArgs/Result types

And move types defined in gopls/internal/vulncheck
to internal/lsp/command so VulncheckResult can use them.

Another approach considered is to encode Vuln as a
json raw message. However, presenting the data structure
in gopls api documentation is too nice to give up.

Updates golang/vscode-go#2096
Updates golang/go#50577

Change-Id: I8587d19f9c47cf786dacaae8cfe1727c77cda711
Reviewed-on: https://go-review.googlesource.com/c/tools/+/395575
Trust: Hyang-Ah Hana Kim <hyangah@gmail.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Hana 2022-03-24 11:50:58 -04:00 committed by Hyang-Ah Hana Kim
parent 84a0321117
commit 4737f45953
4 changed files with 79 additions and 61 deletions

View File

@ -17,64 +17,13 @@ import (
"golang.org/x/exp/vulncheck"
"golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/lsp/command"
"golang.org/x/vuln/client"
)
// CallStack models a trace of function calls starting
// with a client function or method and ending with a
// call to a vulnerable symbol.
type CallStack []StackEntry
// StackEntry models an element of a call stack.
type StackEntry struct {
// See golang.org/x/exp/vulncheck.StackEntry.
// User-friendly representation of function/method names.
// e.g. package.funcName, package.(recvType).methodName, ...
Name string
URI span.URI
Pos protocol.Position // Start position. (0-based. Column is always 0)
}
// Vuln models an osv.Entry and representative call stacks.
type Vuln struct {
// ID is the vulnerability ID (osv.Entry.ID).
// https://ossf.github.io/osv-schema/#id-modified-fields
ID string `json:"id,omitempty"`
// Details is the description of the vulnerability (osv.Entry.Details).
// https://ossf.github.io/osv-schema/#summary-details-fields
Details string `json:"details,omitempty"`
// Aliases are alternative IDs of the vulnerability.
// https://ossf.github.io/osv-schema/#aliases-field
Aliases []string `json:"aliases,omitempty"`
// Symbol is the name of the detected vulnerable function or method.
Symbol string `json:"symbol,omitempty"`
// PkgPath is the package path of the detected Symbol.
PkgPath string `json:"pkg_path,omitempty"`
// ModPath is the module path corresponding to PkgPath.
// TODO: don't we need explicit module version?
// TODO: how do we specify standard library's vulnerability?
ModPath string `json:"mod_path,omitempty"`
// URL is the URL for more info about the information.
// Either the database specific URL or the one of the URLs
// included in osv.Entry.References.
URL string `json:"url,omitempty"`
// Current is the current module version.
CurrentVersion string `json:"current_version,omitempty"`
// Fixed is the minimum module version that contains the fix.
FixedVersion string `json:"fixed_version,omitempty"`
// Example call stacks.
CallStacks []CallStack `json:"call_stacks,omitempty"`
// TODO: import graph & module graph.
}
type Vuln = command.Vuln
type CallStack = command.CallStack
type StackEntry = command.StackEntry
// cmd is an in-process govulncheck command runner
// that uses the provided client.Client.

View File

@ -123,15 +123,15 @@ type report struct {
func toReport(v Vuln) report {
var r = report{Vuln: v}
for _, s := range v.CallStacks {
r.CallStacksStr = append(r.CallStacksStr, s.String())
r.CallStacksStr = append(r.CallStacksStr, CallStackString(s))
}
return r
}
func (callstack CallStack) String() string {
func CallStackString(callstack CallStack) string {
var b bytes.Buffer
for _, entry := range callstack {
fname := filepath.Base(entry.URI.Filename())
fname := filepath.Base(entry.URI.SpanURI().Filename())
fmt.Fprintf(&b, "%v (%v:%d)\n", entry.Name, fname, entry.Pos.Line)
}
return b.String()

View File

@ -14,7 +14,6 @@ import (
"golang.org/x/exp/vulncheck"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/span"
"golang.org/x/vuln/osv"
)
@ -107,11 +106,11 @@ func href(vuln *osv.Entry) string {
return fmt.Sprintf("https://pkg.go.dev/vuln/%s", vuln.ID)
}
func filenameToURI(pos *token.Position) span.URI {
func filenameToURI(pos *token.Position) protocol.DocumentURI {
if pos == nil || pos.Filename == "" {
return ""
}
return span.URIFromPath(pos.Filename)
return protocol.URIFromPath(pos.Filename)
}
func posToPosition(pos *token.Position) (p protocol.Position) {

View File

@ -307,3 +307,73 @@ type DebuggingResult struct {
// will be empty.
URLs []string
}
type VulncheckArgs struct {
// Dir is the directory from which vulncheck will run from.
Dir protocol.DocumentURI
// Package pattern. E.g. "", ".", "./...".
Pattern string
// TODO: Flag []string (flags accepted by govulncheck, e.g., -tests)
// TODO: Format string (json, text)
}
type VulncheckResult struct {
Vuln []Vuln
// TODO: Text string format output?
}
// CallStack models a trace of function calls starting
// with a client function or method and ending with a
// call to a vulnerable symbol.
type CallStack []StackEntry
// StackEntry models an element of a call stack.
type StackEntry struct {
// See golang.org/x/exp/vulncheck.StackEntry.
// User-friendly representation of function/method names.
// e.g. package.funcName, package.(recvType).methodName, ...
Name string
URI protocol.DocumentURI
Pos protocol.Position // Start position. (0-based. Column is always 0)
}
// Vuln models an osv.Entry and representative call stacks.
type Vuln struct {
// ID is the vulnerability ID (osv.Entry.ID).
// https://ossf.github.io/osv-schema/#id-modified-fields
ID string `json:"id,omitempty"`
// Details is the description of the vulnerability (osv.Entry.Details).
// https://ossf.github.io/osv-schema/#summary-details-fields
Details string `json:"details,omitempty"`
// Aliases are alternative IDs of the vulnerability.
// https://ossf.github.io/osv-schema/#aliases-field
Aliases []string `json:"aliases,omitempty"`
// Symbol is the name of the detected vulnerable function or method.
Symbol string `json:"symbol,omitempty"`
// PkgPath is the package path of the detected Symbol.
PkgPath string `json:"pkg_path,omitempty"`
// ModPath is the module path corresponding to PkgPath.
// TODO: how do we specify standard library's vulnerability?
ModPath string `json:"mod_path,omitempty"`
// URL is the URL for more info about the information.
// Either the database specific URL or the one of the URLs
// included in osv.Entry.References.
URL string `json:"url,omitempty"`
// Current is the current module version.
CurrentVersion string `json:"current_version,omitempty"`
// Fixed is the minimum module version that contains the fix.
FixedVersion string `json:"fixed_version,omitempty"`
// Example call stacks.
CallStacks []CallStack `json:"call_stacks,omitempty"`
// TODO: import graph & module graph.
}