gopls/internal/govulncheck: sync x/vuln@62b0186

VulnDB OSV schema was changed recently
  https://go-review.googlesource.com/c/vulndb/+/424895
to fix the misinterpretation of 'affected.package.name',
and the database entries were repopulated with the new schema.
We need to update the client library to pick up the change.
We also need to update the fake vulndb entries used in tests.

gopls/regtest/misc/testdata/vulndb was copied from
  golang.org/x/vuln/cmd/govulncheck/testdata/vulndb @ 62b0186
(the version updated in cl/424895)

Also reverse golang.org/cl/425183 which includes the position
information in the SummarizeCallStack result. Like in govulncheck -v,
the position info is already available in the callstack, thus
this is unnecessary for us. Since x/vuln is currently frozen
until the preview release, revert it from gopls/internal/vulncheck.

Ran go mod tidy -compat=1.16; otherwise, the transitive dependency
on github.com/client9/misspell from golang.org/x/vuln breaks go1.16
build.

Updated copy.sh script to copy x/vuln/internal/semver package
(golang/go#54401) and add the build tags back to all go files.
Gopls's builder builds&tests packages with old go versions,
so we still need go1.18 build tag.

Fixes golang/go#54818

Change-Id: I37770d698082378656a7988d3412a4ca2196ca7b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/427542
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
Hana (Hyang-Ah) Kim 2022-09-01 17:17:06 -04:00 committed by Hyang-Ah Hana Kim
parent 655abda1c0
commit eb8352e307
17 changed files with 313 additions and 32 deletions

View File

@ -10,12 +10,14 @@ require (
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664
golang.org/x/tools v0.1.13-0.20220810174125-0ad49fdeb955
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058
honnef.co/go/tools v0.3.3
mvdan.cc/gofumpt v0.3.1
mvdan.cc/xurls/v2 v2.4.0
)
require golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
require (
github.com/BurntSushi/toml v1.2.0 // indirect
github.com/google/safehtml v0.0.2 // indirect

View File

@ -12,7 +12,6 @@ github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnX
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/google/go-cmdtest v0.4.0/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@ -43,6 +42,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e h1:7Xs2YCOpMlNqSQSmrrnhlzBXIE/bpMecZplbLePTJvE=
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
@ -68,8 +69,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1 h1:wxIK8Hnmd3ervTxk4aON+gAbfWbb2hToeKSTQd0eXgo=
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1/go.mod h1:t0tyWMAuNGUOL2N4il/aj/M5LLt4ktPpOGuTBNUqmiM=
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058 h1:YnB27EXBD8XxB0JcaOeluuvhF2kS4DrH0k+lpopG2xc=
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058/go.mod h1:7tDfEDtOLlzHQRi4Yzfg5seVBSvouUIjyPzBx4q5CxQ=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -11,7 +11,6 @@ package govulncheck
import (
"encoding/json"
"go/build"
"io/ioutil"
"os"
"path/filepath"
"sync"
@ -66,7 +65,7 @@ func (c *FSCache) ReadIndex(dbName string) (client.DBIndex, time.Time, error) {
c.mu.Lock()
defer c.mu.Unlock()
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
b, err := os.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
if err != nil {
if os.IsNotExist(err) {
return nil, time.Time{}, nil
@ -95,7 +94,7 @@ func (c *FSCache) WriteIndex(dbName string, index client.DBIndex, retrieved time
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
if err := os.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
return err
}
return nil
@ -105,7 +104,11 @@ func (c *FSCache) ReadEntries(dbName string, p string) ([]*osv.Entry, error) {
c.mu.Lock()
defer c.mu.Unlock()
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, p, "vulns.json"))
ep, err := client.EscapeModulePath(p)
if err != nil {
return nil, err
}
b, err := os.ReadFile(filepath.Join(c.rootDir, dbName, ep, "vulns.json"))
if err != nil {
if os.IsNotExist(err) {
return nil, nil
@ -123,7 +126,11 @@ func (c *FSCache) WriteEntries(dbName string, p string, entries []*osv.Entry) er
c.mu.Lock()
defer c.mu.Unlock()
path := filepath.Join(c.rootDir, dbName, p)
ep, err := client.EscapeModulePath(p)
if err != nil {
return err
}
path := filepath.Join(c.rootDir, dbName, ep)
if err := os.MkdirAll(path, 0777); err != nil {
return err
}
@ -131,7 +138,7 @@ func (c *FSCache) WriteEntries(dbName string, p string, entries []*osv.Entry) er
if err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
if err := os.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
return err
}
return nil

View File

@ -93,7 +93,7 @@ func TestConcurrency(t *testing.T) {
i := i
g.Go(func() error {
id := i % 5
p := fmt.Sprintf("package%d", id)
p := fmt.Sprintf("example.com/package%d", id)
entries, err := cache.ReadEntries(dbName, p)
if err != nil {
@ -115,7 +115,7 @@ func TestConcurrency(t *testing.T) {
// sanity checking
for i := 0; i < 5; i++ {
id := fmt.Sprint(i)
p := fmt.Sprintf("package%s", id)
p := fmt.Sprintf("example.com/package%s", id)
es, err := cache.ReadEntries(dbName, p)
if err != nil {

View File

@ -11,3 +11,22 @@ set -o pipefail
rm -f *.go
cp ../../../../vuln/cmd/govulncheck/internal/govulncheck/*.go .
sed -i '' 's/\"golang.org\/x\/vuln\/internal\/semver\"/\"golang.org\/x\/tools\/gopls\/internal\/govulncheck\/semver\"/g' *.go
sed -i '' -e '4 i\
' -e '4 i\
//go:build go1.18' -e '4 i\
// +build go1.18' *.go
# Copy golang.org/x/vuln/internal/semver that
# golang.org/x/vuln/cmd/govulncheck/internal/govulncheck
# depends on.
mkdir -p semver
cd semver
rm -f *.go
cp ../../../../../vuln/internal/semver/*.go .
sed -i '' -e '4 i\
' -e '4 i\
//go:build go1.18' -e '4 i\
// +build go1.18' *.go

View File

@ -0,0 +1,38 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package govulncheck
import (
"path/filepath"
"strings"
)
// AbsRelShorter takes path and returns its path relative
// to the current directory, if shorter. Returns path
// when path is an empty string or upon any error.
func AbsRelShorter(path string) string {
if path == "" {
return ""
}
c, err := filepath.Abs(".")
if err != nil {
return path
}
r, err := filepath.Rel(c, path)
if err != nil {
return path
}
rSegments := strings.Split(r, string(filepath.Separator))
pathSegments := strings.Split(path, string(filepath.Separator))
if len(rSegments) < len(pathSegments) {
return r
}
return path
}

View File

@ -0,0 +1,42 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package govulncheck
import (
"os"
"path/filepath"
"testing"
)
func TestAbsRelShorter(t *testing.T) {
thisFile := "filepath_test.go"
thisFileAbs, _ := filepath.Abs(thisFile)
tf, err := os.CreateTemp("", "filepath_test.gp")
if err != nil {
t.Errorf("could not create temporary filepath_test.go file: %v", err)
}
tempFile := tf.Name()
tempFileAbs, _ := filepath.Abs(tempFile)
for _, test := range []struct {
l string
want string
}{
{thisFile, "filepath_test.go"},
{thisFileAbs, "filepath_test.go"},
// Relative path to temp file from "." is longer as
// it needs to go back the length of the absolute
// path and then in addition go to os.TempDir.
{tempFile, tempFileAbs},
} {
if got := AbsRelShorter(test.l); got != test.want {
t.Errorf("want %s; got %s", test.want, got)
}
}
}

View File

@ -0,0 +1,84 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
// Package semver provides shared utilities for manipulating
// Go semantic versions.
package semver
import (
"regexp"
"strings"
)
// addSemverPrefix adds a 'v' prefix to s if it isn't already prefixed
// with 'v' or 'go'. This allows us to easily test go-style SEMVER
// strings against normal SEMVER strings.
func addSemverPrefix(s string) string {
if !strings.HasPrefix(s, "v") && !strings.HasPrefix(s, "go") {
return "v" + s
}
return s
}
// removeSemverPrefix removes the 'v' or 'go' prefixes from go-style
// SEMVER strings, for usage in the public vulnerability format.
func removeSemverPrefix(s string) string {
s = strings.TrimPrefix(s, "v")
s = strings.TrimPrefix(s, "go")
return s
}
// CanonicalizeSemverPrefix turns a SEMVER string into the canonical
// representation using the 'v' prefix, as used by the OSV format.
// Input may be a bare SEMVER ("1.2.3"), Go prefixed SEMVER ("go1.2.3"),
// or already canonical SEMVER ("v1.2.3").
func CanonicalizeSemverPrefix(s string) string {
return addSemverPrefix(removeSemverPrefix(s))
}
var (
// Regexp for matching go tags. The groups are:
// 1 the major.minor version
// 2 the patch version, or empty if none
// 3 the entire prerelease, if present
// 4 the prerelease type ("beta" or "rc")
// 5 the prerelease number
tagRegexp = regexp.MustCompile(`^go(\d+\.\d+)(\.\d+|)((beta|rc|-pre)(\d+))?$`)
)
// This is a modified copy of pkgsite/internal/stdlib:VersionForTag.
func GoTagToSemver(tag string) string {
if tag == "" {
return ""
}
tag = strings.Fields(tag)[0]
// Special cases for go1.
if tag == "go1" {
return "v1.0.0"
}
if tag == "go1.0" {
return ""
}
m := tagRegexp.FindStringSubmatch(tag)
if m == nil {
return ""
}
version := "v" + m[1]
if m[2] != "" {
version += m[2]
} else {
version += ".0"
}
if m[3] != "" {
if !strings.HasPrefix(m[4], "-") {
version += "-"
}
version += m[4] + "." + m[5]
}
return version
}

View File

@ -0,0 +1,43 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.18
// +build go1.18
package semver
import (
"testing"
)
func TestCanonicalize(t *testing.T) {
for _, test := range []struct {
v string
want string
}{
{"v1.2.3", "v1.2.3"},
{"1.2.3", "v1.2.3"},
{"go1.2.3", "v1.2.3"},
} {
got := CanonicalizeSemverPrefix(test.v)
if got != test.want {
t.Errorf("want %s; got %s", test.want, got)
}
}
}
func TestGoTagToSemver(t *testing.T) {
for _, test := range []struct {
v string
want string
}{
{"go1.19", "v1.19.0"},
{"go1.20-pre4", "v1.20.0-pre.4"},
} {
got := GoTagToSemver(test.v)
if got != test.want {
t.Errorf("want %s; got %s", test.want, got)
}
}
}

View File

@ -25,7 +25,7 @@ func (e *PackageError) Error() string {
var b strings.Builder
fmt.Fprintln(&b, "Packages contain errors:")
for _, e := range e.Errors {
fmt.Println(&b, e)
fmt.Fprintln(&b, e)
}
return b.String()
}

View File

@ -12,6 +12,7 @@ import (
"strings"
"golang.org/x/mod/semver"
isem "golang.org/x/tools/gopls/internal/govulncheck/semver"
"golang.org/x/vuln/osv"
"golang.org/x/vuln/vulncheck"
)
@ -24,7 +25,8 @@ func LatestFixed(as []osv.Affected) string {
for _, r := range a.Ranges {
if r.Type == osv.TypeSemver {
for _, e := range r.Events {
if e.Fixed != "" && (v == "" || semver.Compare(e.Fixed, v) > 0) {
if e.Fixed != "" && (v == "" ||
semver.Compare(isem.CanonicalizeSemverPrefix(e.Fixed), isem.CanonicalizeSemverPrefix(v)) > 0) {
v = e.Fixed
}
}
@ -60,12 +62,16 @@ func SummarizeCallStack(cs vulncheck.CallStack, topPkgs map[string]bool, vulnPkg
}
iVuln += iTop + 1 // adjust for slice in call to highest.
topName := FuncName(cs[iTop].Function)
topPos := AbsRelShorter(FuncPos(cs[iTop].Call))
if topPos != "" {
topPos += ": "
}
vulnName := FuncName(cs[iVuln].Function)
if iVuln == iTop+1 {
return fmt.Sprintf("%s calls %s", topName, vulnName)
return fmt.Sprintf("%s%s calls %s", topPos, topName, vulnName)
}
return fmt.Sprintf("%s calls %s, which eventually calls %s",
topName, FuncName(cs[iTop+1].Function), vulnName)
return fmt.Sprintf("%s%s calls %s, which eventually calls %s",
topPos, topName, FuncName(cs[iTop+1].Function), vulnName)
}
// highest returns the highest (one with the smallest index) entry in the call
@ -107,3 +113,11 @@ func PkgPath(fn *vulncheck.FuncNode) string {
func FuncName(fn *vulncheck.FuncNode) string {
return strings.TrimPrefix(fn.String(), "*")
}
// FuncPos returns the function position from call.
func FuncPos(call *vulncheck.CallSite) string {
if call != nil && call.Pos != nil {
return call.Pos.String()
}
return ""
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
[{"id":"GO-2020-0015","published":"2021-04-14T20:04:52Z","modified":"2021-06-07T12:00:00Z","aliases":["CVE-2020-14040"],"details":"An attacker could provide a single byte to a UTF16 decoder instantiated with\nUseBOM or ExpectBOM to trigger an infinite loop if the String function on\nthe Decoder is called, or the Decoder is passed to transform.String.\nIf used to parse user supplied input, this may be used as a denial of service\nvector.\n","affected":[{"package":{"name":"golang.org/x/text/encoding/unicode","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"symbols":["utf16Decoder.Transform","bomOverride.Transform"]}},{"package":{"name":"golang.org/x/text/transform","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"symbols":["Transform"]}}],"references":[{"type":"FIX","url":"https://go-review.googlesource.com/c/text/+/238238"},{"type":"FIX","url":"https://go.googlesource.com/text/+/23ae387dee1f90d29a23c0e87ee0b46038fbed0e"},{"type":"WEB","url":"https://go.dev/issue/39491"},{"type":"WEB","url":"https://groups.google.com/g/golang-announce/c/bXVeAmGOqz0"}]},{"id":"GO-2021-0113","published":"2021-10-06T17:51:21Z","modified":"2021-10-06T17:51:21Z","aliases":["CVE-2021-38561"],"details":"Due to improper index calculation, an incorrectly formatted language tag can cause Parse\nto panic via an out of bounds read. If Parse is used to process untrusted user inputs,\nthis may be used as a vector for a denial of service attack.\n","affected":[{"package":{"name":"golang.org/x/text/language","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.7"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2021-0113"},"ecosystem_specific":{"symbols":["Parse","MatchStrings","MustParse","ParseAcceptLanguage"]}}],"references":[{"type":"FIX","url":"https://go-review.googlesource.com/c/text/+/340830"},{"type":"FIX","url":"https://go.googlesource.com/text/+/383b2e75a7a4198c42f8f87833eefb772868a56f"}]}]
[{"id":"GO-2020-0015","published":"2021-04-14T20:04:52Z","modified":"2021-06-07T12:00:00Z","aliases":["CVE-2020-14040","GHSA-5rcv-m4m3-hfh7"],"details":"An attacker could provide a single byte to a UTF16 decoder instantiated with\nUseBOM or ExpectBOM to trigger an infinite loop if the String function on\nthe Decoder is called, or the Decoder is passed to transform.String.\nIf used to parse user supplied input, this may be used as a denial of service\nvector.\n","affected":[{"package":{"name":"golang.org/x/text","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"imports":[{"path":"golang.org/x/text/encoding/unicode","symbols":["bomOverride.Transform","utf16Decoder.Transform"]},{"path":"golang.org/x/text/transform","symbols":["Transform"]}]}}],"references":[{"type":"FIX","url":"https://go.dev/cl/238238"},{"type":"FIX","url":"https://go.googlesource.com/text/+/23ae387dee1f90d29a23c0e87ee0b46038fbed0e"},{"type":"WEB","url":"https://go.dev/issue/39491"},{"type":"WEB","url":"https://groups.google.com/g/golang-announce/c/bXVeAmGOqz0"},{"type":"WEB","url":"https://nvd.nist.gov/vuln/detail/CVE-2020-14040"},{"type":"WEB","url":"https://github.com/advisories/GHSA-5rcv-m4m3-hfh7"}]},{"id":"GO-2021-0113","published":"2021-10-06T17:51:21Z","modified":"2021-10-06T17:51:21Z","aliases":["CVE-2021-38561"],"details":"Due to improper index calculation, an incorrectly formatted language tag can cause Parse\nto panic via an out of bounds read. If Parse is used to process untrusted user inputs,\nthis may be used as a vector for a denial of service attack.\n","affected":[{"package":{"name":"golang.org/x/text","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.7"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2021-0113"},"ecosystem_specific":{"imports":[{"path":"golang.org/x/text/language","symbols":["MatchStrings","MustParse","Parse","ParseAcceptLanguage"]}]}}],"references":[{"type":"FIX","url":"https://go.dev/cl/340830"},{"type":"FIX","url":"https://go.googlesource.com/text/+/383b2e75a7a4198c42f8f87833eefb772868a56f"},{"type":"WEB","url":"https://nvd.nist.gov/vuln/detail/CVE-2021-38561"}]}]

View File

@ -1 +1 @@
[{"id":"GO-0000-001","affected":[{"package":{"name":"archive/zip"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.18.0"}]}],"ecosystem_specific":{"symbols":["OpenReader"]}}]}]
[{"id":"STD","affected":[{"package":{"name":"stdlib"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.18.0"}]}],"ecosystem_specific":{"imports":[{"path":"archive/zip","symbols":["OpenReader"]}]}}]}]

View File

@ -61,7 +61,7 @@ import (
)
func main() {
_, err := zip.OpenReader("file.zip") // vulnerability GO-0000-001
_, err := zip.OpenReader("file.zip") // vulnerability id: STD
fmt.Println(err)
}
`
@ -111,7 +111,7 @@ func main() {
env.Await(
CompletedWork("govulncheck", 1, true),
// TODO(hyangah): once the diagnostics are published, wait for diagnostics.
ShownMessage("Found GO-0000-001"),
ShownMessage("Found STD"),
)
})
}

View File

@ -175,7 +175,10 @@ func toVulns(ci *gvc.CallInfo, unaffectedMods map[string][]*osv.Entry) ([]Vuln,
for _, v := range vg {
if css := ci.CallStacks[v]; len(css) > 0 {
vuln.CallStacks = append(vuln.CallStacks, toCallStack(css[0]))
vuln.CallStackSummaries = append(vuln.CallStackSummaries, gvc.SummarizeCallStack(css[0], ci.TopPackages, v.PkgPath))
// TODO(hyangah): https://go-review.googlesource.com/c/vuln/+/425183 added position info
// in the summary but we don't need the info. Allow SummarizeCallStack to skip it optionally.
sum := trimPosPrefix(gvc.SummarizeCallStack(css[0], ci.TopPackages, v.PkgPath))
vuln.CallStackSummaries = append(vuln.CallStackSummaries, sum)
}
}
vulns = append(vulns, vuln)
@ -196,3 +199,11 @@ func toVulns(ci *gvc.CallInfo, unaffectedMods map[string][]*osv.Entry) ([]Vuln,
}
return vulns, nil
}
func trimPosPrefix(summary string) string {
_, after, found := strings.Cut(summary, ": ")
if !found {
return summary
}
return after
}

View File

@ -14,6 +14,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
@ -42,6 +43,13 @@ func TestCmd_Run(t *testing.T) {
for _, v := range result {
got = append(got, toReport(v))
}
// drop the workspace root directory path included in the summary.
cwd := cfg.Dir
for _, g := range got {
for i, summary := range g.CallStackSummaries {
g.CallStackSummaries[i] = strings.ReplaceAll(summary, cwd, ".")
}
}
var want = []report{
{
@ -232,9 +240,13 @@ var testClient1 = &mockClient{
},
},
Affected: []osv.Affected{{
Package: osv.Package{Name: "golang.org/amod/avuln"},
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}},
Package: osv.Package{Name: "golang.org/amod"},
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
EcosystemSpecific: osv.EcosystemSpecific{
Imports: []osv.EcosystemSpecificImport{{
Path: "golang.org/amod/avuln",
Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}}},
},
}},
},
{
@ -247,9 +259,13 @@ var testClient1 = &mockClient{
},
},
Affected: []osv.Affected{{
Package: osv.Package{Name: "golang.org/amod/avuln"},
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"nonExisting"}},
Package: osv.Package{Name: "golang.org/amod"},
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
EcosystemSpecific: osv.EcosystemSpecific{
Imports: []osv.EcosystemSpecificImport{{
Path: "golang.org/amod/avuln",
Symbols: []string{"nonExisting"}}},
},
}},
},
},
@ -257,9 +273,13 @@ var testClient1 = &mockClient{
{
ID: "GO-2022-02",
Affected: []osv.Affected{{
Package: osv.Package{Name: "golang.org/bmod/bvuln"},
Ranges: osv.Affects{{Type: osv.TypeSemver}},
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"Vuln"}},
Package: osv.Package{Name: "golang.org/bmod"},
Ranges: osv.Affects{{Type: osv.TypeSemver}},
EcosystemSpecific: osv.EcosystemSpecific{
Imports: []osv.EcosystemSpecificImport{{
Path: "golang.org/bmod/bvuln",
Symbols: []string{"Vuln"}}},
},
}},
},
},