Julie Qiu submitted this change.
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
vulncheck: delete
This package has been moved to golang.org/x/vuln/vulncheck. It is
deleted here to prevent confusion.
Change-Id: I613fa3688489b1a8f1d8b933614edcc747deb34b
Reviewed-on: https://go-review.googlesource.com/c/exp/+/395256
Reviewed-by: Jonathan Amsterdam <j...@google.com>
Trust: Julie Qiu <ju...@golang.org>
Run-TryBot: Julie Qiu <ju...@golang.org>
TryBot-Result: Gopher Robot <go...@golang.org>
---
D vulncheck/all.bash
D vulncheck/all_test.go
D vulncheck/binary.go
D vulncheck/binary_test.go
D vulncheck/checks.bash
D vulncheck/entries.go
D vulncheck/fetch.go
D vulncheck/fetch_test.go
D vulncheck/go.mod
D vulncheck/go.sum
D vulncheck/helpers_test.go
D vulncheck/internal/binscan/exe.go
D vulncheck/internal/binscan/scan.go
D vulncheck/internal/binscan/scan_test.go
D vulncheck/internal/derrors/derrors.go
D vulncheck/lib.sh
D vulncheck/slicing.go
D vulncheck/slicing_test.go
D vulncheck/source.go
D vulncheck/source_test.go
D vulncheck/tools_test.go
D vulncheck/utils.go
D vulncheck/vulncheck.go
D vulncheck/vulncheck_test.go
D vulncheck/witness.go
D vulncheck/witness_test.go
26 files changed, 17 insertions(+), 4,879 deletions(-)
diff --git a/vulncheck/all.bash b/vulncheck/all.bash
deleted file mode 100755
index 70704c7..0000000
--- a/vulncheck/all.bash
+++ /dev/null
@@ -1,174 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2021 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.
-
-if [[ $(basename $PWD) == "exp" ]]; then
- cd vulncheck
-fi
-
-RED=; GREEN=; YELLOW=; BLUE=; BOLD=; RESET=;
-
-case $TERM in
- '' | xterm) ;;
- # If xterm is not xterm-16color, xterm-88color, or xterm-256color, tput will
- # return the error:
- # tput: No value for $TERM and no -T specified
- *)
- RED=`tput setaf 1`
- GREEN=`tput setaf 2`
- YELLOW=`tput setaf 3`
- NORMAL=`tput sgr0`
-esac
-
-EXIT_CODE=0
-
-info() { echo -e "${GREEN}$@${NORMAL}" 1>&2; }
-err() { echo -e "${RED}$@${NORMAL}" 1>&2; EXIT_CODE=1; }
-
-# runcud prints an info log describing the command that is about to be run, and
-# then runs it. It sets EXIT_CODE to non-zero if the command fails, but does not exit
-# the script.
-runcmd() {
- # Truncate command logging for narrow terminals.
- # Account for the 2 characters of '$ '.
- maxwidth=$(( $(tput cols) - 2 ))
- if [[ ${#msg} -gt $maxwidth ]]; then
- msg="${msg::$(( maxwidth - 3 ))}..."
- fi
-
- echo -e "$@\n" 1>&2;
- $@ || err "command failed"
-}
-
-# ensure_go_binary verifies that a binary exists in $PATH corresponding to the
-# given go-gettable URI. If no such binary exists, it is fetched via `go get`.
-ensure_go_binary() {
- local binary=$(basename $1)
- if ! [ -x "$(command -v $binary)" ]; then
- info "Installing: $1"
- # Install the binary in a way that doesn't affect our go.mod file.
- go install $1@latest
- fi
-}
-
-# verify_header checks that all given files contain the standard header for Go
-# projects.
-verify_header() {
- if [[ "$@" != "" ]]; then
- for FILE in $@
- do
- line="$(head -1 $FILE)"
- if [[ ! $line == *"The Go Authors. All rights reserved."* ]] &&
- [[ ! $line == "// DO NOT EDIT. This file was copied from" ]]; then
- err "missing license header: $FILE"
- fi
- done
- fi
-}
-
-# Support ** in globs for findcode.
-shopt -s globstar
-
-# findcode finds source files in the repo.
-findcode() {
- find **/*.go
-}
-
-# check_headers checks that all source files that have been staged in this
-# commit, and all other non-third-party files in the repo, have a license
-# header.
-check_headers() {
- if [[ $# -gt 0 ]]; then
- info "Checking listed files for license header"
- verify_header $*
- else
- info "Checking staged files for license header"
- # Check code files that have been modified or added.
- verify_header $(git diff --cached --name-status | grep -vE "^D" | cut -f 2- | grep -E ".go$|.sh$")
- info "Checking go files for license header"
- verify_header $(findcode)
- fi
-}
-
-# check_unparam runs unparam on source files.
-check_unparam() {
- ensure_go_binary mvdan.cc/unparam
- runcmd unparam ./...
-}
-
-# check_vet runs go vet on source files.
-check_vet() {
- runcmd go vet -all ./...
-}
-
-# check_staticcheck runs staticcheck on source files.
-check_staticcheck() {
- ensure_go_binary honnef.co/go/tools/cmd/staticcheck
- runcmd staticcheck ./...
-}
-
-# check_misspell runs misspell on source files.
-check_misspell() {
- ensure_go_binary github.com/client9/misspell/cmd/misspell
- runcmd misspell -error .
-}
-
-go_linters() {
- check_vet
- check_staticcheck
- check_misspell
- check_unparam
-}
-
-go_modtidy() {
- runcmd go mod tidy
-}
-
-go_test() {
- runcmd go test ./...
-}
-
-runchecks() {
- check_headers
- go_linters
- go_modtidy
- go_test
-}
-
-usage() {
- cat <<EOUSAGE
-Usage: $0 [subcommand]
-Available subcommands:
- (empty) - run all standard checks and tests:
- * headers: check source files for the license disclaimer
- * vet: run go vet on source files
- * staticcheck: run staticcheck on source files
- * misspell: run misspell on source files
- * unparam: run unparam on source files
- * tidy: run go mod tidy
- * tests: run all Go tests
- help - display this help message
-EOUSAGE
-}
-
-main() {
- case "$1" in
- "-h" | "--help" | "help")
- usage
- exit 0
- ;;
- "")
- runchecks
- ;;
- *)
- usage
- exit 1
- esac
- if [[ $EXIT_CODE != 0 ]]; then
- err "FAILED; see errors above"
- fi
- exit $EXIT_CODE
-}
-
-main $@
diff --git a/vulncheck/all_test.go b/vulncheck/all_test.go
deleted file mode 100644
index 30a18b3..0000000
--- a/vulncheck/all_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2021 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.17 && !windows
-// +build go1.17,!windows
-
-package vulncheck
-
-import (
- "os"
- "os/exec"
- "testing"
-)
-
-func TestChecksBash(t *testing.T) {
- bash, err := exec.LookPath("bash")
- if err != nil {
- t.Skipf("skipping: %v", err)
- }
-
- cmd := exec.Command(bash, "./checks.bash")
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- if err := cmd.Run(); err != nil {
- t.Fatal(err)
- }
-}
diff --git a/vulncheck/binary.go b/vulncheck/binary.go
deleted file mode 100644
index eeefd90..0000000
--- a/vulncheck/binary.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "io"
- "runtime"
-
- "golang.org/x/exp/vulncheck/internal/binscan"
- "golang.org/x/exp/vulncheck/internal/derrors"
- "golang.org/x/tools/go/packages"
-)
-
-// Binary detects presence of vulnerable symbols in exe. The
-// imports, require, and call graph are all unavailable (nil).
-func Binary(ctx context.Context, exe io.ReaderAt, cfg *Config) (_ *Result, err error) {
- defer derrors.Wrap(&err, "vulncheck.Binary")
-
- mods, packageSymbols, err := binscan.ExtractPackagesAndSymbols(exe)
- if err != nil {
- return nil, err
- }
- modVulns, err := fetchVulnerabilities(ctx, cfg.Client, convertModules(mods))
- if err != nil {
- return nil, err
- }
- modVulns = modVulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
-
- result := &Result{}
- for pkg, symbols := range packageSymbols {
- if cfg.ImportsOnly {
- addImportsOnlyVulns(pkg, symbols, result, modVulns)
- } else {
- addSymbolVulns(pkg, symbols, result, modVulns)
- }
- }
- return result, nil
-}
-
-// addImportsOnlyVulns adds Vuln entries to result in imports only mode, i.e., for each vulnerable symbol
-// of pkg.
-func addImportsOnlyVulns(pkg string, symbols []string, result *Result, modVulns moduleVulnerabilities) {
- for _, osv := range modVulns.VulnsForPackage(pkg) {
- for _, affected := range osv.Affected {
- if affected.Package.Name != pkg {
- continue
- }
-
- var syms []string
- if len(affected.EcosystemSpecific.Symbols) == 0 {
- // If every symbol of pkg is vulnerable, we would ideally compute
- // every symbol mentioned in the pkg and then add Vuln entry for it,
- // just as we do in Source. However, we don't have code of pkg here
- // so we have to do best we can, which is the symbols of pkg actually
- // appearing in the binary.
- syms = symbols
- } else {
- syms = affected.EcosystemSpecific.Symbols
- }
-
- for _, symbol := range syms {
- vuln := &Vuln{
- OSV: osv,
- Symbol: symbol,
- PkgPath: pkg,
- // TODO(zpavlinovic): infer mod path from PkgPath and modules?
- }
- result.Vulns = append(result.Vulns, vuln)
- }
- }
- }
-}
-
-// addSymbolVulns adds Vuln entries to result for every symbol of pkg in the binary that is vulnerable.
-func addSymbolVulns(pkg string, symbols []string, result *Result, modVulns moduleVulnerabilities) {
- for _, symbol := range symbols {
- for _, osv := range modVulns.VulnsForSymbol(pkg, symbol) {
- for _, affected := range osv.Affected {
- if affected.Package.Name != pkg {
- continue
- }
- vuln := &Vuln{
- OSV: osv,
- Symbol: symbol,
- PkgPath: pkg,
- // TODO(zpavlinovic): infer mod path from PkgPath and modules?
- }
- result.Vulns = append(result.Vulns, vuln)
- break
- }
- }
- }
-}
-
-func convertModules(mods []*packages.Module) []*Module {
- vmods := make([]*Module, len(mods))
- // TODO(github.com/golang/go/issues/50030): should we share unique
- // modules? Not needed nowas module info is not returned by Binary.
- for i, mod := range mods {
- vmods[i] = &Module{
- Path: mod.Path,
- Version: mod.Version,
- }
- if mod.Replace != nil {
- vmods[i].Replace = &Module{
- Path: mod.Replace.Path,
- Version: mod.Replace.Version,
- }
- }
- }
- return vmods
-}
diff --git a/vulncheck/binary_test.go b/vulncheck/binary_test.go
deleted file mode 100644
index 63c090f..0000000
--- a/vulncheck/binary_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "testing"
-
- "golang.org/x/tools/go/packages/packagestest"
-)
-
-// TODO: we build binary programatically, so what if the underlying tool chain changes?
-func TestBinary(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "main.go": `
- package main
-
- import (
- "golang.org/cmod/c"
- "golang.org/bmod/bvuln"
- )
-
- func main() {
- c.C()
- bvuln.NoVuln() // no vuln use
- print("done")
- }
- `,
- }},
- {
- Name: "golang.org/cm...@v1.1.3",
- Files: map[string]interface{}{"c/c.go": `
- package c
-
- import (
- "golang.org/amod/avuln"
- )
-
- //go:noinline
- func C() {
- v := avuln.VulnData{}
- v.Vuln1() // vuln use
- }
- `},
- },
- {
- Name: "golang.org/am...@v1.1.3",
- Files: map[string]interface{}{"avuln/avuln.go": `
- package avuln
-
- type VulnData struct {}
-
- //go:noinline
- func (v VulnData) Vuln1() {}
-
- //go:noinline
- func (v VulnData) Vuln2() {}
- `},
- },
- {
- Name: "golang.org/bm...@v0.5.0",
- Files: map[string]interface{}{"bvuln/bvuln.go": `
- package bvuln
-
- //go:noinline
- func Vuln() {}
-
- //go:noinline
- func NoVuln() {}
- `},
- },
- })
- defer e.Cleanup()
-
- cmd := exec.Command("go", "build")
- cmd.Dir = e.Config.Dir
- cmd.Env = e.Config.Env
- out, err := cmd.CombinedOutput()
- if err != nil || len(out) > 0 {
- t.Fatalf("failed to build the binary %v %v", err, string(out))
- }
-
- binExt := ""
- // TODO: is there a better way to do this?
- if runtime.GOOS == "windows" {
- binExt = ".exe"
- }
-
- bin, err := os.Open(filepath.Join(e.Config.Dir, "entry"+binExt))
- if err != nil {
- t.Fatalf("failed to access the binary %v", err)
- }
- defer bin.Close()
-
- // Test imports only mode
- cfg := &Config{
- Client: testClient,
- ImportsOnly: true,
- }
- res, err := Binary(context.Background(), bin, cfg)
- if err != nil {
- t.Fatal(err)
- }
- // In importsOnly mode, all three vulnerable symbols
- // {avuln.VulnData.Vuln1, avuln.VulnData.Vuln2, bvuln.Vuln}
- // should be detected.
- if len(res.Vulns) != 3 {
- t.Errorf("expected 3 vuln symbols; got %d", len(res.Vulns))
- }
-
- // Test the symbols (non-import mode)
- cfg = &Config{Client: testClient}
- res, err = Binary(context.Background(), bin, cfg)
- if err != nil {
- t.Fatal(err)
- }
- // In non-importsOnly mode, only one symbol avuln.VulnData.Vuln1 should be detected.
- if len(res.Vulns) != 1 {
- t.Errorf("expected 1 vuln symbols got %d", len(res.Vulns))
- }
-}
diff --git a/vulncheck/checks.bash b/vulncheck/checks.bash
deleted file mode 100755
index 770dc28..0000000
--- a/vulncheck/checks.bash
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2021 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.
-
-# This file will be run by `go test`.
-# See all_test.go in this directory.
-
-# Ensure that installed go binaries are on the path.
-# This bash expression follows the algorithm described at the top of
-# `go install help`: first try $GOBIN, then $GOPATH/bin, then $HOME/go/bin.
-go_install_dir=${GOBIN:-${GOPATH:-$HOME/go}/bin}
-PATH=$PATH:$go_install_dir
-
-source ../devtools/checklib.sh
-
-# check_unparam runs unparam on source files.
-check_unparam() {
- ensure_go_binary mvdan.cc/unparam
- runcmd unparam ./...
-}
-
-# check_staticcheck runs staticcheck on source files.
-check_staticcheck() {
- if [[ $(go version) = *go1.17* ]]; then
- ensure_go_binary honnef.co/go/tools/cmd/staticcheck
- runcmd staticcheck ./...
- fi
-}
-
-# check_misspell runs misspell on source files.
-check_misspell() {
- ensure_go_binary github.com/client9/misspell/cmd/misspell
- runcmd misspell -error .
-}
-
-runchecks() {
- check_header *.go internal/*/*.go *.bash
- runcmd go vet -all ./...
- check_staticcheck
- check_unparam
- check_misspell
- runcmd go mod tidy
-}
-
-main() {
- runchecks
- if [[ $EXIT_CODE != 0 ]]; then
- err "FAILED; see errors above"
- fi
- exit $EXIT_CODE
-}
-
-main $@
diff --git a/vulncheck/entries.go b/vulncheck/entries.go
deleted file mode 100644
index 834d590..0000000
--- a/vulncheck/entries.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "strings"
-
- "golang.org/x/tools/go/ssa"
-)
-
-func entryPoints(topPackages []*ssa.Package) []*ssa.Function {
- var entries []*ssa.Function
- for _, pkg := range topPackages {
- if pkg.Pkg.Name() == "main" {
- // for "main" packages the only valid entry points are the "main"
- // function and any "init#" functions, even if there are other
- // exported functions or types. similarly to isEntry it should be
- // safe to ignore the validity of the main or init# signatures,
- // since the compiler will reject malformed definitions,
- // and the init function is synthetic
- entries = append(entries, memberFuncs(pkg.Members["main"], pkg.Prog)...)
- for name, member := range pkg.Members {
- if strings.HasPrefix(name, "init#") || name == "init" {
- entries = append(entries, memberFuncs(member, pkg.Prog)...)
- }
- }
- continue
- }
- for _, member := range pkg.Members {
- for _, f := range memberFuncs(member, pkg.Prog) {
- if isEntry(f) {
- entries = append(entries, f)
- }
- }
- }
- }
- return entries
-}
-
-func isEntry(f *ssa.Function) bool {
- // it should be safe to ignore checking that the signature of the "init" function
- // is valid, since it is synthetic
- if f.Name() == "init" && f.Synthetic == "package initializer" {
- return true
- }
-
- return f.Synthetic == "" && f.Object() != nil && f.Object().Exported()
-}
diff --git a/vulncheck/fetch.go b/vulncheck/fetch.go
deleted file mode 100644
index bc8cce2..0000000
--- a/vulncheck/fetch.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "fmt"
-
- "golang.org/x/vuln/client"
-)
-
-// modKey creates a unique string identifier for mod.
-func modKey(mod *Module) string {
- if mod == nil {
- return ""
- }
- return fmt.Sprintf("%s@%s", mod.Path, mod.Version)
-}
-
-// extractModules collects modules in `pkgs` up to uniqueness of
-// module path and version.
-func extractModules(pkgs []*Package) []*Module {
- modMap := map[string]*Module{}
-
- seen := map[*Package]bool{}
- var extract func(*Package, map[string]*Module)
- extract = func(pkg *Package, modMap map[string]*Module) {
- if pkg == nil || seen[pkg] {
- return
- }
- if pkg.Module != nil {
- if pkg.Module.Replace != nil {
- modMap[modKey(pkg.Module.Replace)] = pkg.Module
- } else {
- modMap[modKey(pkg.Module)] = pkg.Module
- }
- }
- seen[pkg] = true
- for _, imp := range pkg.Imports {
- extract(imp, modMap)
- }
- }
- for _, pkg := range pkgs {
- extract(pkg, modMap)
- }
-
- modules := []*Module{}
- for _, mod := range modMap {
- modules = append(modules, mod)
- }
- return modules
-}
-
-// fetchVulnerabilities fetches vulnerabilities that affect the supplied modules.
-func fetchVulnerabilities(ctx context.Context, client client.Client, modules []*Module) (moduleVulnerabilities, error) {
- mv := moduleVulnerabilities{}
- for _, mod := range modules {
- modPath := mod.Path
- if mod.Replace != nil {
- modPath = mod.Replace.Path
- }
-
- vulns, err := client.GetByModule(ctx, modPath)
- if err != nil {
- return nil, err
- }
- if len(vulns) == 0 {
- continue
- }
- mv = append(mv, modVulns{
- mod: mod,
- vulns: vulns,
- })
- }
- return mv, nil
-}
diff --git a/vulncheck/fetch_test.go b/vulncheck/fetch_test.go
deleted file mode 100644
index da7fd88..0000000
--- a/vulncheck/fetch_test.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "reflect"
- "testing"
-
- "golang.org/x/vuln/osv"
-)
-
-func TestFetchVulnerabilities(t *testing.T) {
- mc := &mockClient{
- ret: map[string][]*osv.Entry{
- "example.mod/a": {{ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}}},
- "example.mod/b": {{ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.1.1"}}}}}}}},
- "example.mod/d": {{ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}}},
- "example.mod/e": {{ID: "e", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/e"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.2.0"}}}}}}}},
- },
- }
-
- mv, err := fetchVulnerabilities(context.Background(), mc, []*Module{
- {Path: "example.mod/a", Version: "v1.0.0"},
- {Path: "example.mod/b", Version: "v1.0.4"},
- {Path: "example.mod/c", Replace: &Module{Path: "example.mod/d", Version: "v1.0.0"}, Version: "v2.0.0"},
- {Path: "example.mod/e", Replace: &Module{Path: "../local/example.mod/d", Version: "v1.0.1"}, Version: "v2.1.0"},
- })
- if err != nil {
- t.Fatalf("FetchVulnerabilities failed: %s", err)
- }
-
- expected := moduleVulnerabilities{
- {
- mod: &Module{Path: "example.mod/a", Version: "v1.0.0"},
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
- },
- },
- {
- mod: &Module{Path: "example.mod/b", Version: "v1.0.4"},
- vulns: []*osv.Entry{
- {ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.1.1"}}}}}}},
- },
- },
- {
- mod: &Module{Path: "example.mod/c", Replace: &Module{Path: "example.mod/d", Version: "v1.0.0"}, Version: "v2.0.0"},
- vulns: []*osv.Entry{
- {ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
- },
- },
- }
- if !reflect.DeepEqual(mv, expected) {
- t.Fatalf("FetchVulnerabilities returned unexpected results, got:\n%s\nwant:\n%s", moduleVulnerabilitiesToString(mv), moduleVulnerabilitiesToString(expected))
- }
-}
diff --git a/vulncheck/go.mod b/vulncheck/go.mod
deleted file mode 100644
index 056fc37..0000000
--- a/vulncheck/go.mod
+++ /dev/null
@@ -1,40 +0,0 @@
-module golang.org/x/exp/vulncheck
-
-go 1.17
-
-require (
- github.com/client9/misspell v0.3.4
- golang.org/x/tools v0.1.8
- golang.org/x/vuln v0.0.0-20211207171702-7209860d2c63
- honnef.co/go/tools v0.1.3
- mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5
-)
-
-require (
- cloud.google.com/go v0.97.0 // indirect
- cloud.google.com/go/errorreporting v0.1.0 // indirect
- github.com/BurntSushi/toml v0.3.1 // indirect
- github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect
- github.com/cespare/xxhash v1.1.0 // indirect
- github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 // indirect
- github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed // indirect
- github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 // indirect
- github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect
- github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
- github.com/golang/protobuf v1.5.2 // indirect
- github.com/google/go-cmp v0.5.6 // indirect
- github.com/googleapis/gax-go/v2 v2.1.1 // indirect
- go.opencensus.io v0.23.0 // indirect
- golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 // indirect
- golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
- golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 // indirect
- golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
- golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827 // indirect
- golang.org/x/text v0.3.7 // indirect
- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
- google.golang.org/api v0.60.0 // indirect
- google.golang.org/appengine v1.6.7 // indirect
- google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351 // indirect
- google.golang.org/grpc v1.40.0 // indirect
- google.golang.org/protobuf v1.27.1 // indirect
-)
diff --git a/vulncheck/go.sum b/vulncheck/go.sum
deleted file mode 100644
index bf70cca..0000000
--- a/vulncheck/go.sum
+++ /dev/null
@@ -1,920 +0,0 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.92.2/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
-cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
-cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
-cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/errorreporting v0.1.0 h1:z40EhrjRspplwbpO+9DSnC4kgDokBi94T/gYwtdKL5Q=
-cloud.google.com/go/errorreporting v0.1.0/go.mod h1:cZSiBMvrnl0X13pD9DwKf9sQ8Eqy3EzHqkyKBZxiIrM=
-cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
-cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
-cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
-cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
-github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
-github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
-github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
-github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
-github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
-github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
-github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
-github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
-github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
-github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
-github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
-github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
-github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
-github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
-github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
-github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
-github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
-github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
-github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
-github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
-github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
-github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
-github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
-github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
-github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
-github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
-github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
-github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
-github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
-github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0=
-github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
-github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
-github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
-github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
-github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
-github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
-github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
-github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
-github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
-github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU=
-github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
-github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
-github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
-github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
-github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
-github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
-github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
-github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
-github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/jba/templatecheck v0.6.0/go.mod h1:/1k7EajoSErFI9GLHAsiIJEaNLt3ALKNw2TV7z2SYv4=
-github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
-github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
-github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
-github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
-github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
-github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
-github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
-github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
-github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
-github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
-github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
-github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
-github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
-github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
-github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
-github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
-github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
-github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
-github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
-github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
-github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
-github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
-github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
-github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
-github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
-github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
-github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
-github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
-github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
-github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
-github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
-github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
-github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
-github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
-github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
-github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
-go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
-go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
-go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU=
-go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw=
-go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
-go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
-go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
-go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
-go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
-golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20211123021643-48cbe7f80d7c h1:hp+QRBz/P/780ndA1Rv/UpvsR6AsVmOMGYitxgZ1PPA=
-golang.org/x/exp v0.0.0-20211123021643-48cbe7f80d7c/go.mod h1:b9TAUYHmRtqA6klRHApnXMnj+OyLce4yF5cZCUbk2ps=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
-golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
-golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57 h1:LQmS1nU0twXLA96Kt7U9qtHJEbBk3z6Q0V4UXjZkpr4=
-golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
-golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE=
-golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827 h1:A0Qkn7Z/n8zC1xd9LTw17AiKlBRK64tw3ejWQiEqca0=
-golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/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/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
-golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
-golang.org/x/vuln v0.0.0-20211207171702-7209860d2c63 h1:pKwhHArAWkz04s3lSHKpF34o0tDEbNSTyFDFuWZ0Jzw=
-golang.org/x/vuln v0.0.0-20211207171702-7209860d2c63/go.mod h1:zIQqHjf9sHpn0TOli6Vdy9mrmuePs9lmnGBRAzECxz0=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
-google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
-google.golang.org/api v0.60.0 h1:eq/zs5WPH4J9undYM9IP1O7dSr7Yh8Y0GtSCpzGzIUk=
-google.golang.org/api v0.60.0/go.mod h1:d7rl65NZAkEQ90JFzqBjcRq1TVeG5ZoGV3sSpEnnVb4=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351 h1:uf3hR4mj3fn7tjJL1f0kkRqFE7GDPoBiyvLxvu1Gt/g=
-google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
-google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
-gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
-gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
-gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.1.3 h1:qTakTkI6ni6LFD5sBwwsdSO+AQqbSIxOauHTTQKZ/7o=
-honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
-mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 h1:Jh3LAeMt1eGpxomyu3jVkmVZWW2MxZ1qIIV2TZ/nRio=
-mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5/go.mod h1:b8RRCBm0eeiWR8cfN88xeq2G5SG3VKGO+5UPWi5FSOY=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
-sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
diff --git a/vulncheck/helpers_test.go b/vulncheck/helpers_test.go
deleted file mode 100644
index ddfe8ec..0000000
--- a/vulncheck/helpers_test.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "fmt"
- "sort"
-
- "golang.org/x/tools/go/packages"
- "golang.org/x/tools/go/packages/packagestest"
- "golang.org/x/vuln/client"
- "golang.org/x/vuln/osv"
-)
-
-type mockClient struct {
- client.Client
- ret map[string][]*osv.Entry
-}
-
-func (mc *mockClient) GetByModule(ctx context.Context, a string) ([]*osv.Entry, error) {
- return mc.ret[a], nil
-}
-
-// testClient contains the following test vulnerabilities
-// golang.org/amod/avuln.{VulnData.Vuln1, vulnData.Vuln2}
-// golang.org/bmod/bvuln.{Vuln}
-var testClient = &mockClient{
- ret: map[string][]*osv.Entry{
- "golang.org/amod": []*osv.Entry{
- {
- ID: "VA",
- 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"}},
- }},
- },
- },
- "golang.org/bmod": []*osv.Entry{
- {
- ID: "VB",
- Affected: []osv.Affected{{
- Package: osv.Package{Name: "golang.org/bmod/bvuln"},
- Ranges: osv.Affects{{Type: osv.TypeSemver}},
- EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"Vuln"}},
- }},
- },
- },
- },
-}
-
-func moduleVulnerabilitiesToString(mv moduleVulnerabilities) string {
- var s string
- for _, m := range mv {
- s += fmt.Sprintf("mod: %v\n", m.mod)
- for _, v := range m.vulns {
- s += fmt.Sprintf("\t%v\n", v)
- }
- }
- return s
-}
-
-func vulnsToString(vulns []*osv.Entry) string {
- var s string
- for _, v := range vulns {
- s += fmt.Sprintf("\t%v\n", v)
- }
- return s
-}
-
-func impGraphToStrMap(ig *ImportGraph) map[string][]string {
- m := make(map[string][]string)
- for _, n := range ig.Packages {
- for _, predId := range n.ImportedBy {
- pred := ig.Packages[predId]
- m[pred.Path] = append(m[pred.Path], n.Path)
- }
- }
-
- sortStrMap(m)
- return m
-}
-
-func reqGraphToStrMap(rg *RequireGraph) map[string][]string {
- m := make(map[string][]string)
- for _, n := range rg.Modules {
- for _, predId := range n.RequiredBy {
- pred := rg.Modules[predId]
- m[pred.Path] = append(m[pred.Path], n.Path)
- }
- }
-
- sortStrMap(m)
- return m
-}
-
-func callGraphToStrMap(cg *CallGraph) map[string][]string {
- type edge struct {
- // src and dest are ids ofr source and
- // destination nodes in a callgraph edge.
- src, dst int
- }
- // seen edges, to avoid repetitions
- seen := make(map[edge]bool)
-
- m := make(map[string][]string)
- for _, n := range cg.Functions {
- fName := n.String()
- for _, callsite := range n.CallSites {
- e := edge{src: callsite.Parent, dst: n.ID}
- if seen[e] {
- continue
- }
- caller := cg.Functions[e.src]
- callerName := caller.String()
- m[callerName] = append(m[callerName], fName)
- }
- }
-
- sortStrMap(m)
- return m
-}
-
-func pkgPathToImports(pkgs []*Package) map[string][]string {
- m := make(map[string][]string)
- seen := make(map[*Package]bool)
- var visit func(*Package)
- visit = func(p *Package) {
- if seen[p] {
- return
- }
- seen[p] = true
- var imports []string
- for _, i := range p.Imports {
- imports = append(imports, i.PkgPath)
- visit(i)
- }
- m[p.PkgPath] = imports
- }
- for _, p := range pkgs {
- visit(p)
- }
- sortStrMap(m)
- return m
-}
-
-func modulePathToVersion(pkgs []*Package) map[string]string {
- m := make(map[string]string)
- seen := make(map[*Package]bool)
- var visit func(*Package)
- visit = func(p *Package) {
- if seen[p] || p.Module == nil {
- return
- }
- seen[p] = true
- for _, i := range p.Imports {
- visit(i)
- }
- m[p.Module.Path] = p.Module.Version
- }
- for _, p := range pkgs {
- visit(p)
- }
- return m
-}
-
-// sortStrMap sorts the map string slice values to make them deterministic.
-func sortStrMap(m map[string][]string) {
- for _, strs := range m {
- sort.Strings(strs)
- }
-}
-
-func loadPackages(e *packagestest.Exported, patterns ...string) ([]*packages.Package, error) {
- e.Config.Mode |= packages.NeedModule | packages.NeedName | packages.NeedFiles |
- packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes |
- packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps
- return packages.Load(e.Config, patterns...)
-}
diff --git a/vulncheck/internal/binscan/exe.go b/vulncheck/internal/binscan/exe.go
deleted file mode 100644
index 37399e1..0000000
--- a/vulncheck/internal/binscan/exe.go
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2021 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.
-
-package binscan
-
-// This file is a somewhat modified version of cmd/go/internal/version/exe.go
-// that adds functionality for extracting the PCLN table.
-
-import (
- "bytes"
- "debug/elf"
- "debug/macho"
- "debug/pe"
- "encoding/binary"
- "fmt"
-
- // "internal/xcoff"
- "io"
-)
-
-// An exe is a generic interface to an OS executable (ELF, Mach-O, PE, XCOFF).
-type exe interface {
- // ReadData reads and returns up to size byte starting at virtual address addr.
- ReadData(addr, size uint64) ([]byte, error)
-
- // DataStart returns the writable data segment start address.
- DataStart() uint64
-
- PCLNTab() ([]byte, uint64)
-}
-
-// openExe returns reader r as an exe.
-func openExe(r io.ReaderAt) (exe, error) {
- data := make([]byte, 16)
- if _, err := r.ReadAt(data, 0); err != nil {
- return nil, err
- }
- if bytes.HasPrefix(data, []byte("\x7FELF")) {
- e, err := elf.NewFile(r)
- if err != nil {
- return nil, err
- }
- return &elfExe{e}, nil
- }
- if bytes.HasPrefix(data, []byte("MZ")) {
- e, err := pe.NewFile(r)
- if err != nil {
- return nil, err
- }
- return &peExe{r, e}, nil
- }
- if bytes.HasPrefix(data, []byte("\xFE\xED\xFA")) || bytes.HasPrefix(data[1:], []byte("\xFA\xED\xFE")) {
- e, err := macho.NewFile(r)
- if err != nil {
- return nil, err
- }
- return &machoExe{e}, nil
- }
- // TODO(rolandshoemaker): we cannot support XCOFF files due to the usage of internal/xcoff.
- // Once this code is moved into the stdlib, this support can be re-enabled.
- // if bytes.HasPrefix(data, []byte{0x01, 0xDF}) || bytes.HasPrefix(data, []byte{0x01, 0xF7}) {
- // e, err := xcoff.NewFile(r)
- // if err != nil {
- // return nil, err
- // }
- // return &xcoffExe{e}, nil
-
- // }
- return nil, fmt.Errorf("unrecognized executable format")
-}
-
-// elfExe is the ELF implementation of the exe interface.
-type elfExe struct {
- f *elf.File
-}
-
-func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
- for _, prog := range x.f.Progs {
- if prog.Vaddr <= addr && addr <= prog.Vaddr+prog.Filesz-1 {
- n := prog.Vaddr + prog.Filesz - addr
- if n > size {
- n = size
- }
- data := make([]byte, n)
- _, err := prog.ReadAt(data, int64(addr-prog.Vaddr))
- if err != nil {
- return nil, err
- }
- return data, nil
- }
- }
- return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *elfExe) DataStart() uint64 {
- for _, s := range x.f.Sections {
- if s.Name == ".go.buildinfo" {
- return s.Addr
- }
- }
- for _, p := range x.f.Progs {
- if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
- return p.Vaddr
- }
- }
- return 0
-}
-
-const go12magic = 0xfffffffb
-const go116magic = 0xfffffffa
-
-func (x *elfExe) PCLNTab() ([]byte, uint64) {
- var offset uint64
- text := x.f.Section(".text")
- if text != nil {
- offset = text.Offset
- }
- pclntab := x.f.Section(".gopclntab")
- if pclntab == nil {
- pclntab = x.f.Section(".data.rel.ro.gopclntab")
- if pclntab == nil {
- pclntab = x.f.Section(".data.rel.ro")
- if pclntab == nil {
- return nil, 0
- }
- // Possibly the PCLN table has been stuck in the .data.rel.ro section, but without
- // its own section header. We can search for for the start by looking for the four
- // byte magic and the go magic.
- b, err := pclntab.Data()
- if err != nil {
- return nil, 0
- }
- // TODO(rolandshoemaker): I'm not sure if the 16 byte increment during the search is
- // actually correct. During testing it worked, but that may be because I got lucky
- // with the binary I was using, and we need to do four byte jumps to exhaustively
- // search the section?
- for i := 0; i < len(b); i += 16 {
- if len(b)-i > 16 && b[i+4] == 0 && b[i+5] == 0 &&
- (b[i+6] == 1 || b[i+6] == 2 || b[i+6] == 4) &&
- (b[i+7] == 4 || b[i+7] == 8) {
- // Also check for the go magic
- leMagic := binary.LittleEndian.Uint32(b[i:])
- beMagic := binary.BigEndian.Uint32(b[i:])
- switch {
- case leMagic == go12magic:
- fallthrough
- case beMagic == go12magic:
- fallthrough
- case leMagic == go116magic:
- fallthrough
- case beMagic == go116magic:
- return b[i:], offset
- }
- }
- }
- }
- }
- b, err := pclntab.Data()
- if err != nil {
- return nil, 0
- }
- return b, offset
-}
-
-// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
-type peExe struct {
- r io.ReaderAt
- f *pe.File
-}
-
-func (x *peExe) imageBase() uint64 {
- switch oh := x.f.OptionalHeader.(type) {
- case *pe.OptionalHeader32:
- return uint64(oh.ImageBase)
- case *pe.OptionalHeader64:
- return oh.ImageBase
- }
- return 0
-}
-
-func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
- addr -= x.imageBase()
- for _, sect := range x.f.Sections {
- if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
- n := uint64(sect.VirtualAddress+sect.Size) - addr
- if n > size {
- n = size
- }
- data := make([]byte, n)
- _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
- if err != nil {
- return nil, err
- }
- return data, nil
- }
- }
- return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *peExe) DataStart() uint64 {
- // Assume data is first writable section.
- const (
- IMAGE_SCN_CNT_CODE = 0x00000020
- IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040
- IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080
- IMAGE_SCN_MEM_EXECUTE = 0x20000000
- IMAGE_SCN_MEM_READ = 0x40000000
- IMAGE_SCN_MEM_WRITE = 0x80000000
- IMAGE_SCN_MEM_DISCARDABLE = 0x2000000
- IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000
- IMAGE_SCN_ALIGN_32BYTES = 0x600000
- )
- for _, sect := range x.f.Sections {
- if sect.VirtualAddress != 0 && sect.Size != 0 &&
- sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
- return uint64(sect.VirtualAddress) + x.imageBase()
- }
- }
- return 0
-}
-
-func (x *peExe) PCLNTab() ([]byte, uint64) {
- var textOffset uint64
- for _, section := range x.f.Sections {
- if section.Name == ".text" {
- textOffset = uint64(section.Offset)
- break
- }
- }
- var start, end int64
- var section int
- for _, symbol := range x.f.Symbols {
- if symbol.Name == "runtime.pclntab" {
- start = int64(symbol.Value)
- section = int(symbol.SectionNumber - 1)
- } else if symbol.Name == "runtime.epclntab" {
- end = int64(symbol.Value)
- break
- }
- }
- if start == 0 || end == 0 {
- return nil, 0
- }
- offset := int64(x.f.Sections[section].Offset) + start
- size := end - start
-
- pclntab := make([]byte, size)
- if _, err := x.r.ReadAt(pclntab, offset); err != nil {
- return nil, 0
- }
-
- return pclntab, textOffset
-}
-
-// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
-type machoExe struct {
- f *macho.File
-}
-
-func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
- for _, load := range x.f.Loads {
- seg, ok := load.(*macho.Segment)
- if !ok {
- continue
- }
- if seg.Addr <= addr && addr <= seg.Addr+seg.Filesz-1 {
- if seg.Name == "__PAGEZERO" {
- continue
- }
- n := seg.Addr + seg.Filesz - addr
- if n > size {
- n = size
- }
- data := make([]byte, n)
- _, err := seg.ReadAt(data, int64(addr-seg.Addr))
- if err != nil {
- return nil, err
- }
- return data, nil
- }
- }
- return nil, fmt.Errorf("address not mapped")
-}
-
-func (x *machoExe) DataStart() uint64 {
- // Look for section named "__go_buildinfo".
- for _, sec := range x.f.Sections {
- if sec.Name == "__go_buildinfo" {
- return sec.Addr
- }
- }
- // Try the first non-empty writable segment.
- const RW = 3
- for _, load := range x.f.Loads {
- seg, ok := load.(*macho.Segment)
- if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
- return seg.Addr
- }
- }
- return 0
-}
-
-func (x *machoExe) PCLNTab() ([]byte, uint64) {
- var textOffset uint64
- text := x.f.Section("__text")
- if text != nil {
- textOffset = uint64(text.Offset)
- }
- pclntab := x.f.Section("__gopclntab")
- if pclntab == nil {
- return nil, 0
- }
- b, err := pclntab.Data()
- if err != nil {
- return nil, 0
- }
- return b, textOffset
-}
-
-// TODO(rolandshoemaker): we cannot support XCOFF files due to the usage of internal/xcoff.
-// Once this code is moved into the stdlib, this support can be re-enabled.
-
-// // xcoffExe is the XCOFF (AIX eXtended COFF) implementation of the exe interface.
-// type xcoffExe struct {
-// f *xcoff.File
-// }
-//
-// func (x *xcoffExe) ReadData(addr, size uint64) ([]byte, error) {
-// for _, sect := range x.f.Sections {
-// if uint64(sect.VirtualAddress) <= addr && addr <= uint64(sect.VirtualAddress+sect.Size-1) {
-// n := uint64(sect.VirtualAddress+sect.Size) - addr
-// if n > size {
-// n = size
-// }
-// data := make([]byte, n)
-// _, err := sect.ReadAt(data, int64(addr-uint64(sect.VirtualAddress)))
-// if err != nil {
-// return nil, err
-// }
-// return data, nil
-// }
-// }
-// return nil, fmt.Errorf("address not mapped")
-// }
-//
-// func (x *xcoffExe) DataStart() uint64 {
-// return x.f.SectionByType(xcoff.STYP_DATA).VirtualAddress
-// }
diff --git a/vulncheck/internal/binscan/scan.go b/vulncheck/internal/binscan/scan.go
deleted file mode 100644
index 35d0fcd..0000000
--- a/vulncheck/internal/binscan/scan.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2021 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.
-
-// Package binscan contains methods for parsing Go binary files for the purpose
-// of extracting module dependency and symbol table information.
-package binscan
-
-// Code in this package is dervied from src/cmd/go/internal/version/version.go
-// and cmd/go/internal/version/exe.go.
-
-import (
- "debug/buildinfo"
- "debug/gosym"
- "errors"
- "fmt"
- "io"
- "net/url"
- "runtime/debug"
- "strings"
-
- "golang.org/x/tools/go/packages"
-)
-
-func debugModulesToPackagesModules(debugModules []*debug.Module) []*packages.Module {
- packagesModules := make([]*packages.Module, len(debugModules))
- for i, mod := range debugModules {
- packagesModules[i] = &packages.Module{
- Path: mod.Path,
- Version: mod.Version,
- }
- if mod.Replace != nil {
- packagesModules[i].Replace = &packages.Module{
- Path: mod.Replace.Path,
- Version: mod.Replace.Version,
- }
- }
- }
- return packagesModules
-}
-
-// ExtractPackagesAndSymbols extracts the symbols, packages, and their associated module versions
-// from a Go binary. Stripped binaries are not supported.
-//
-// TODO(#51412): detect inlined symbols too
-func ExtractPackagesAndSymbols(bin io.ReaderAt) ([]*packages.Module, map[string][]string, error) {
- bi, err := buildinfo.Read(bin)
- if err != nil {
- return nil, nil, err
- }
-
- x, err := openExe(bin)
- if err != nil {
- return nil, nil, err
- }
-
- pclntab, textOffset := x.PCLNTab()
- if pclntab == nil {
- // TODO(roland): if we have build information, but not PCLN table, we should be able to
- // fall back to much higher granularity vulnerability checking.
- return nil, nil, errors.New("unable to load the PCLN table")
- }
- lineTab := gosym.NewLineTable(pclntab, textOffset)
- if lineTab == nil {
- return nil, nil, errors.New("invalid line table")
- }
- tab, err := gosym.NewTable(nil, lineTab)
- if err != nil {
- return nil, nil, err
- }
-
- packageSymbols := map[string][]string{}
- for _, f := range tab.Funcs {
- if f.Func == nil {
- continue
- }
- symName := f.Func.BaseName()
- if r := f.Func.ReceiverName(); r != "" {
- if strings.HasPrefix(r, "(*") {
- r = strings.Trim(r, "(*)")
- }
- symName = fmt.Sprintf("%s.%s", r, symName)
- }
-
- pkgName := f.Func.PackageName()
- if pkgName == "" {
- continue
- }
- pkgName, err := url.PathUnescape(pkgName)
- if err != nil {
- return nil, nil, err
- }
-
- packageSymbols[pkgName] = append(packageSymbols[pkgName], symName)
- }
-
- return debugModulesToPackagesModules(bi.Deps), packageSymbols, nil
-}
diff --git a/vulncheck/internal/binscan/scan_test.go b/vulncheck/internal/binscan/scan_test.go
deleted file mode 100644
index b87554c..0000000
--- a/vulncheck/internal/binscan/scan_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2021 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.
-
-package binscan
-
-// TODO(zpavlinovic): add tests.
diff --git a/vulncheck/internal/derrors/derrors.go b/vulncheck/internal/derrors/derrors.go
deleted file mode 100644
index 7f1ea9f..0000000
--- a/vulncheck/internal/derrors/derrors.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 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.
-
-// Package derrors defines internal error values to categorize the different
-// types error semantics supported by the vulndb.
-package derrors
-
-import "fmt"
-
-// Wrap adds context to the error and allows
-// unwrapping the result to recover the original error.
-//
-// Example:
-//
-// defer derrors.Wrap(&err, "copy(%s, %s)", dst, src)
-func Wrap(errp *error, format string, args ...interface{}) {
- if *errp != nil {
- *errp = fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), *errp)
- }
-}
diff --git a/vulncheck/lib.sh b/vulncheck/lib.sh
deleted file mode 100644
index 1304d3a..0000000
--- a/vulncheck/lib.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2021 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.
-
-# Library of useful bash functions and variables.
-
-RED=; GREEN=; YELLOW=; NORMAL=;
-MAXWIDTH=0
-
-if tput setaf 1 >& /dev/null; then
- RED=`tput setaf 1`
- GREEN=`tput setaf 2`
- YELLOW=`tput setaf 3`
- NORMAL=`tput sgr0`
- MAXWIDTH=$(( $(tput cols) - 2 ))
-fi
-
-EXIT_CODE=0
-
-info() { echo -e "${GREEN}$@${NORMAL}" 1>&2; }
-warn() { echo -e "${YELLOW}$@${NORMAL}" 1>&2; }
-err() { echo -e "${RED}$@${NORMAL}" 1>&2; EXIT_CODE=1; }
-
-die() {
- err $@
- exit 1
-}
-
-dryrun=false
-
-# runcmd prints an info log describing the command that is about to be run, and
-# then runs it. It sets EXIT_CODE to non-zero if the command fails, but does not exit
-# the script.
-runcmd() {
- msg="$@"
- if $dryrun; then
- echo -e "${YELLOW}dryrun${GREEN}\$ $msg${NORMAL}"
- return 0
- fi
- # Truncate command logging for narrow terminals.
- # Account for the 2 characters of '$ '.
- if [[ $MAXWIDTH -gt 0 && ${#msg} -gt $MAXWIDTH ]]; then
- msg="${msg::$(( MAXWIDTH - 3 ))}..."
- fi
-
- echo -e "$@\n" 1>&2;
- $@ || err "command failed"
-}
-
-# tfvar NAME returns the value of NAME in the terraform.tfvars file.
-tfvar() {
- local name=$1
- awk '$1 == "'$name'" { print substr($3, 2, length($3)-2) }' terraform/terraform.tfvars
-}
diff --git a/vulncheck/slicing.go b/vulncheck/slicing.go
deleted file mode 100644
index 7f76787..0000000
--- a/vulncheck/slicing.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "golang.org/x/tools/go/callgraph"
- "golang.org/x/tools/go/ssa"
-)
-
-// forwardReachableFrom computes the set of functions forward reachable from `sources`.
-// A function f is reachable from a function g if f is an anonymous function defined
-// in g or a function called in g as given by the callgraph `cg`.
-func forwardReachableFrom(sources map[*ssa.Function]bool, cg *callgraph.Graph) map[*ssa.Function]bool {
- m := make(map[*ssa.Function]bool)
- for s := range sources {
- forward(s, cg, m)
- }
- return m
-}
-
-func forward(f *ssa.Function, cg *callgraph.Graph, seen map[*ssa.Function]bool) {
- if seen[f] {
- return
- }
- seen[f] = true
- var buf [10]*ssa.Value // avoid alloc in common case
- for _, b := range f.Blocks {
- for _, instr := range b.Instrs {
- switch i := instr.(type) {
- case ssa.CallInstruction:
- for _, c := range siteCallees(i, cg) {
- forward(c, cg, seen)
- }
- default:
- for _, op := range i.Operands(buf[:0]) {
- if fn, ok := (*op).(*ssa.Function); ok {
- forward(fn, cg, seen)
- }
- }
- }
- }
- }
-}
-
-// pruneSet removes functions in `set` that are in `toPrune`.
-func pruneSet(set, toPrune map[*ssa.Function]bool) {
- for f := range set {
- if !toPrune[f] {
- delete(set, f)
- }
- }
-}
diff --git a/vulncheck/slicing_test.go b/vulncheck/slicing_test.go
deleted file mode 100644
index ae8bfb8..0000000
--- a/vulncheck/slicing_test.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "path"
- "reflect"
- "testing"
-
- "golang.org/x/tools/go/callgraph/cha"
- "golang.org/x/tools/go/packages/packagestest"
- "golang.org/x/tools/go/ssa"
- "golang.org/x/tools/go/ssa/ssautil"
-)
-
-// funcNames returns a set of function names for `funcs`.
-func funcNames(funcs map[*ssa.Function]bool) map[string]bool {
- fs := make(map[string]bool)
- for f := range funcs {
- fs[dbFuncName(f)] = true
- }
- return fs
-}
-
-func TestSlicing(t *testing.T) {
- // test program
- p := `
-package slice
-
-func X() {}
-func Y() {}
-
-// not reachable
-func id(i int) int {
- return i
-}
-
-// not reachable
-func inc(i int) int {
- return i + 1
-}
-
-func Apply(b bool, h func()) {
- if b {
- func() {
- print("applied")
- }()
- return
- }
- h()
-}
-
-type I interface {
- Foo()
-}
-
-type A struct{}
-
-func (a A) Foo() {}
-
-// not reachable
-func (a A) Bar() {}
-
-type B struct{}
-
-func (b B) Foo() {}
-
-func debug(s string) {
- print(s)
-}
-
-func Do(i I, input string) {
- debug(input)
-
- i.Foo()
-
- func(x string) {
- func(l int) {
- print(l)
- }(len(x))
- }(input)
-}`
-
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "some/module",
- Files: map[string]interface{}{"slice/slice.go": p},
- },
- })
-
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "/module/slice"))
- if err != nil {
- t.Fatal(err)
- }
- prog, ssaPkgs := ssautil.AllPackages(pkgs, 0)
- prog.Build()
-
- pkg := ssaPkgs[0]
- sources := map[*ssa.Function]bool{pkg.Func("Apply"): true, pkg.Func("Do"): true}
- fs := funcNames(forwardReachableFrom(sources, cha.CallGraph(prog)))
- want := map[string]bool{
- "Apply": true,
- "Apply$1": true,
- "X": true,
- "Y": true,
- "Do": true,
- "Do$1": true,
- "Do$1$1": true,
- "debug": true,
- "A.Foo": true,
- "B.Foo": true,
- }
- if !reflect.DeepEqual(want, fs) {
- t.Errorf("want %v; got %v", want, fs)
- }
-}
diff --git a/vulncheck/source.go b/vulncheck/source.go
deleted file mode 100644
index 2ad0cf7..0000000
--- a/vulncheck/source.go
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "fmt"
- "go/token"
- "runtime"
-
- "golang.org/x/exp/vulncheck/internal/derrors"
- "golang.org/x/tools/go/callgraph"
- "golang.org/x/tools/go/ssa"
- "golang.org/x/vuln/osv"
-)
-
-// Source detects vulnerabilities in pkgs and computes slices of
-// - imports graph related to an import of a package with some
-// known vulnerabilities
-// - requires graph related to a require of a module with a
-// package that has some known vulnerabilities
-// - call graph leading to the use of a known vulnerable function
-// or method
-func Source(ctx context.Context, pkgs []*Package, cfg *Config) (_ *Result, err error) {
- defer derrors.Wrap(&err, "vulncheck.Source")
-
- // buildSSA builds a whole program that assumes all packages use the same FileSet.
- // Check all packages in pkgs are using the same FileSet.
- // TODO(hyangah): Alternative is to take FileSet out of Package and
- // let Source take a single FileSet. That will make the enforcement
- // clearer from the API level.
- var fset *token.FileSet
- for _, p := range pkgs {
- if fset == nil {
- fset = p.Fset
- } else {
- if fset != p.Fset {
- return nil, fmt.Errorf("[]*Package must have created with the same FileSet")
- }
- }
- }
-
- modVulns, err := fetchVulnerabilities(ctx, cfg.Client, extractModules(pkgs))
- if err != nil {
- return nil, err
- }
- modVulns = modVulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
-
- result := &Result{
- Imports: &ImportGraph{Packages: make(map[int]*PkgNode)},
- Requires: &RequireGraph{Modules: make(map[int]*ModNode)},
- Calls: &CallGraph{Functions: make(map[int]*FuncNode)},
- }
-
- vulnPkgModSlice(pkgs, modVulns, result)
- if cfg.ImportsOnly {
- return result, nil
- }
-
- prog, ssaPkgs := buildSSA(pkgs, fset)
- entries := entryPoints(ssaPkgs)
- cg := callGraph(prog, entries)
- vulnCallGraphSlice(entries, modVulns, cg, result)
-
- return result, nil
-}
-
-// pkgID is an id counter for nodes of Imports graph.
-var pkgID int = 0
-
-func nextPkgID() int {
- pkgID++
- return pkgID
-}
-
-// vulnPkgModSlice computes the slice of pkgs imports and requires graph
-// leading to imports/requires of vulnerable packages/modules in modVulns
-// and stores the computed slices to result.
-func vulnPkgModSlice(pkgs []*Package, modVulns moduleVulnerabilities, result *Result) {
- // analyzedPkgs contains information on packages analyzed thus far.
- // If a package is mapped to nil, this means it has been visited
- // but it does not lead to a vulnerable imports. Otherwise, a
- // visited package is mapped to Imports package node.
- analyzedPkgs := make(map[*Package]*PkgNode)
- for _, pkg := range pkgs {
- // Top level packages that lead to vulnerable imports are
- // stored as result.Imports graph entry points.
- if e := vulnImportSlice(pkg, modVulns, result, analyzedPkgs); e != nil {
- result.Imports.Entries = append(result.Imports.Entries, e.ID)
- }
- }
-
- // Populate module requires slice as an overlay
- // of package imports slice.
- vulnModuleSlice(result)
-}
-
-// vulnImportSlice checks if pkg has some vulnerabilities or transitively imports
-// a package with known vulnerabilities. If that is the case, populates result.Imports
-// graph with this reachability information and returns the result.Imports package
-// node for pkg. Otherwise, returns nil.
-func vulnImportSlice(pkg *Package, modVulns moduleVulnerabilities, result *Result, analyzed map[*Package]*PkgNode) *PkgNode {
- if pn, ok := analyzed[pkg]; ok {
- return pn
- }
- analyzed[pkg] = nil
- // Recursively compute which direct dependencies lead to an import of
- // a vulnerable package and remember the nodes of such dependencies.
- var onSlice []*PkgNode
- for _, imp := range pkg.Imports {
- if impNode := vulnImportSlice(imp, modVulns, result, analyzed); impNode != nil {
- onSlice = append(onSlice, impNode)
- }
- }
-
- // Check if pkg has known vulnerabilities.
- vulns := modVulns.VulnsForPackage(pkg.PkgPath)
-
- // If pkg is not vulnerable nor it transitively leads
- // to vulnerabilities, jump out.
- if len(onSlice) == 0 && len(vulns) == 0 {
- return nil
- }
-
- // Module id gets populated later.
- id := nextPkgID()
- pkgNode := &PkgNode{
- ID: id,
- Name: pkg.Name,
- Path: pkg.PkgPath,
- pkg: pkg,
- }
- analyzed[pkg] = pkgNode
-
- result.Imports.Packages[id] = pkgNode
-
- // Save node predecessor information.
- for _, impSliceNode := range onSlice {
- impSliceNode.ImportedBy = append(impSliceNode.ImportedBy, id)
- }
-
- // Create Vuln entry for each symbol of known OSV entries for pkg.
- for _, osv := range vulns {
- for _, affected := range osv.Affected {
- if affected.Package.Name != pkgNode.Path {
- continue
- }
-
- var symbols []string
- if len(affected.EcosystemSpecific.Symbols) != 0 {
- symbols = affected.EcosystemSpecific.Symbols
- } else {
- symbols = allSymbols(pkg.Pkg)
- }
-
- for _, symbol := range symbols {
- vuln := &Vuln{
- OSV: osv,
- Symbol: symbol,
- PkgPath: pkgNode.Path,
- ImportSink: id,
- }
- result.Vulns = append(result.Vulns, vuln)
- }
- }
- }
- return pkgNode
-}
-
-// vulnModuleSlice populates result.Requires as an overlay
-// of result.Imports.
-func vulnModuleSlice(result *Result) {
- // Map from module nodes, identified with their
- // path and version, to their unique ids.
- modNodeIDs := make(map[string]int)
- // We first collect inverse requires by (predecessor)
- // relation on module node ids.
- modPredRelation := make(map[int]map[int]bool)
- for _, pkgNode := range result.Imports.Packages {
- // Create or get module node for pkgNode.
- pkgModID := moduleNodeID(pkgNode, result, modNodeIDs)
- pkgNode.Module = pkgModID
-
- // Get the set of predecessors.
- predSet := make(map[int]bool)
- for _, predPkgID := range pkgNode.ImportedBy {
- predModID := moduleNodeID(result.Imports.Packages[predPkgID], result, modNodeIDs)
- predSet[predModID] = true
- }
- modPredRelation[pkgModID] = predSet
- }
-
- // Add entry module IDs.
- seenEntries := make(map[int]bool)
- for _, epID := range result.Imports.Entries {
- entryModID := moduleNodeID(result.Imports.Packages[epID], result, modNodeIDs)
- if seenEntries[entryModID] {
- continue
- }
- seenEntries[entryModID] = true
- result.Requires.Entries = append(result.Requires.Entries, entryModID)
- }
-
- // Store the predecessor requires relation to result.
- for modID := range modPredRelation {
- if modID == 0 {
- continue
- }
-
- var predIDs []int
- for predID := range modPredRelation[modID] {
- predIDs = append(predIDs, predID)
- }
- modNode := result.Requires.Modules[modID]
- modNode.RequiredBy = predIDs
- }
-
- // And finally update Vulns with module information.
- for _, vuln := range result.Vulns {
- pkgNode := result.Imports.Packages[vuln.ImportSink]
- modNode := result.Requires.Modules[pkgNode.Module]
-
- vuln.RequireSink = pkgNode.Module
- vuln.ModPath = modNode.Path
- }
-}
-
-// modID is an id counter for nodes of Requires graph.
-var modID int = 0
-
-func nextModID() int {
- modID++
- return modID
-}
-
-// moduleNode creates a module node associated with pkgNode, if one does
-// not exist already, and returns id of the module node. The actual module
-// node is stored to result.
-func moduleNodeID(pkgNode *PkgNode, result *Result, modNodeIDs map[string]int) int {
- mod := pkgNode.pkg.Module
- if mod == nil {
- return 0
- }
-
- mk := modKey(mod)
- if id, ok := modNodeIDs[mk]; ok {
- return id
- }
-
- id := nextModID()
- n := &ModNode{
- ID: id,
- Path: mod.Path,
- Version: mod.Version,
- }
- result.Requires.Modules[id] = n
- modNodeIDs[mk] = id
-
- // Create a replace module too when applicable.
- if mod.Replace != nil {
- rmk := modKey(mod.Replace)
- if rid, ok := modNodeIDs[rmk]; ok {
- n.Replace = rid
- } else {
- rid := nextModID()
- rn := &ModNode{
- Path: mod.Replace.Path,
- Version: mod.Replace.Version,
- }
- result.Requires.Modules[rid] = rn
- modNodeIDs[rmk] = rid
- n.Replace = rid
- }
- }
- return id
-}
-
-func vulnCallGraphSlice(entries []*ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result) {
- // analyzedFuncs contains information on functions analyzed thus far.
- // If a function is mapped to nil, this means it has been visited
- // but it does not lead to a vulnerable call. Otherwise, a visited
- // function is mapped to Calls function node.
- analyzedFuncs := make(map[*ssa.Function]*FuncNode)
- for _, entry := range entries {
- // Top level entries that lead to vulnerable calls
- // are stored as result.Calls graph entry points.
- if e := vulnCallSlice(entry, modVulns, cg, result, analyzedFuncs); e != nil {
- result.Calls.Entries = append(result.Calls.Entries, e.ID)
- }
- }
-}
-
-// funID is an id counter for nodes of Calls graph.
-var funID int = 0
-
-func nextFunID() int {
- funID++
- return funID
-}
-
-// vulnCallSlice checks if f has some vulnerabilities or transitively calls
-// a function with known vulnerabilities. If so, populates result.Calls
-// graph with this reachability information and returns the result.Call
-// function node. Otherwise, returns nil.
-func vulnCallSlice(f *ssa.Function, modVulns moduleVulnerabilities, cg *callgraph.Graph, result *Result, analyzed map[*ssa.Function]*FuncNode) *FuncNode {
- if fn, ok := analyzed[f]; ok {
- return fn
- }
-
- fn := cg.Nodes[f]
- if fn == nil {
- return nil
- }
-
- // Check if f has known vulnerabilities.
- vulns := modVulns.VulnsForSymbol(pkgPath(f), dbFuncName(f))
-
- var funNode *FuncNode
- // If there are vulnerabilities for f, create node for f and
- // save it immediately. This allows us to include F in the
- // slice when analyzing chain V -> F -> V where V is vulnerable.
- if len(vulns) > 0 {
- funNode = funcNode(f)
- }
- analyzed[f] = funNode
-
- // Recursively compute which callees lead to a call of a
- // vulnerable function. Remember the nodes of such callees.
- type siteNode struct {
- call ssa.CallInstruction
- fn *FuncNode
- }
- var onSlice []siteNode
- for _, edge := range fn.Out {
- if calleeNode := vulnCallSlice(edge.Callee.Func, modVulns, cg, result, analyzed); calleeNode != nil {
- onSlice = append(onSlice, siteNode{call: edge.Site, fn: calleeNode})
- }
- }
-
- // If f is not vulnerable nor it transitively leads
- // to vulnerable calls, jump out.
- if len(onSlice) == 0 && len(vulns) == 0 {
- return nil
- }
-
- // If f is not vulnerable, then at this point it has
- // to be on the path leading to a vulnerable call.
- if funNode == nil {
- funNode = funcNode(f)
- analyzed[f] = funNode
- }
- result.Calls.Functions[funNode.ID] = funNode
-
- // Save node predecessor information.
- for _, calleeSliceInfo := range onSlice {
- call, node := calleeSliceInfo.call, calleeSliceInfo.fn
- cs := &CallSite{
- Parent: funNode.ID,
- Name: call.Common().Value.Name(),
- RecvType: callRecvType(call),
- Resolved: resolved(call),
- Pos: instrPosition(call),
- }
- node.CallSites = append(node.CallSites, cs)
- }
-
- // Populate CallSink field for each detected vuln symbol.
- for _, osv := range vulns {
- for _, affected := range osv.Affected {
- if affected.Package.Name != funNode.PkgPath {
- continue
- }
- addCallSinkForVuln(funNode.ID, osv, dbFuncName(f), funNode.PkgPath, result)
- }
- }
- return funNode
-}
-
-// pkgPath returns the path of the f's enclosing package, if any.
-// Otherwise, returns "".
-func pkgPath(f *ssa.Function) string {
- if f.Package() != nil && f.Package().Pkg != nil {
- return f.Package().Pkg.Path()
- }
- return ""
-}
-
-func funcNode(f *ssa.Function) *FuncNode {
- id := nextFunID()
- return &FuncNode{
- ID: id,
- Name: f.Name(),
- PkgPath: pkgPath(f),
- RecvType: funcRecvType(f),
- Pos: funcPosition(f),
- }
-}
-
-// addCallSinkForVuln adds callID as call sink to vuln of result.Vulns
-// identified with <osv, symbol, pkg>.
-func addCallSinkForVuln(callID int, osv *osv.Entry, symbol, pkg string, result *Result) {
- for _, vuln := range result.Vulns {
- if vuln.OSV == osv && vuln.Symbol == symbol && vuln.PkgPath == pkg {
- vuln.CallSink = callID
- return
- }
- }
-}
diff --git a/vulncheck/source_test.go b/vulncheck/source_test.go
deleted file mode 100644
index 6d65706..0000000
--- a/vulncheck/source_test.go
+++ /dev/null
@@ -1,552 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "context"
- "os"
- "path"
- "reflect"
- "testing"
-
- "golang.org/x/tools/go/packages/packagestest"
- "golang.org/x/vuln/osv"
-)
-
-// TestImportsOnly checks for module and imports graph correctness
-// for the Config.ImportsOnly=true mode. The inlined test code has
-// the following package (left) and module (right) imports graphs:
-//
-// entry/x entry/y entry
-// \ / \ / \
-// amod/avuln zmod/z amod zmod
-// | |
-// wmod/w wmod
-// | |
-// bmod/bvuln bmod
-//
-// Packages ending in "vuln" have some known vulnerabilities.
-func TestImportsOnly(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "x/x.go": `
- package x
-
- import "golang.org/amod/avuln"
-
- func X() {
- avuln.VulnData{}.Vuln1()
- }
- `,
- "y/y.go": `
- package y
-
- import (
- "golang.org/amod/avuln"
- "golang.org/zmod/z"
- )
-
- func Y() {
- avuln.VulnData{}.Vuln2()
- z.Z()
- }
- `}},
- {
- Name: "golang.org/zm...@v0.0.0",
- Files: map[string]interface{}{"z/z.go": `
- package z
-
- func Z() {}
- `},
- },
- {
- Name: "golang.org/am...@v1.1.3",
- Files: map[string]interface{}{"avuln/avuln.go": `
- package avuln
-
- import "golang.org/wmod/w"
-
- type VulnData struct {}
- func (v VulnData) Vuln1() { w.W() }
- func (v VulnData) Vuln2() {}
- `},
- },
- {
- Name: "golang.org/bm...@v0.5.0",
- Files: map[string]interface{}{"bvuln/bvuln.go": `
- package bvuln
-
- func Vuln() {}
- `},
- },
- {
- Name: "golang.org/wm...@v0.0.0",
- Files: map[string]interface{}{"w/w.go": `
- package w
-
- import "golang.org/bmod/bvuln"
-
- func W() { bvuln.Vuln() }
- `},
- },
- })
- defer e.Cleanup()
-
- // Load x and y as entry packages.
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"), path.Join(e.Temp(), "entry/y"))
- if err != nil {
- t.Fatal(err)
- }
-
- if len(pkgs) != 2 {
- t.Fatal("failed to load x and y test packages")
- }
-
- cfg := &Config{
- Client: testClient,
- ImportsOnly: true,
- }
- result, err := Source(context.Background(), Convert(pkgs), cfg)
- if err != nil {
- t.Fatal(err)
- }
-
- // Check that we find the right number of vulnerabilities.
- // There should be three entries as there are three vulnerable
- // symbols in the two import-reachable OSVs.
- if len(result.Vulns) != 3 {
- t.Errorf("want 3 Vulns, got %d", len(result.Vulns))
- }
-
- // Check that vulnerabilities are connected to the imports
- // and requires graph.
- for _, v := range result.Vulns {
- if v.ImportSink == 0 || v.RequireSink == 0 {
- t.Errorf("want ImportSink !=0 and RequireSink !=0 for %v:%v; got %v and %v", v.Symbol, v.PkgPath, v.ImportSink, v.RequireSink)
- }
- }
-
- // Check that module and package entry points are collected.
- if got := len(result.Imports.Entries); got != 2 {
- t.Errorf("want 2 package entry points; got %v", got)
- }
- if got := len(result.Requires.Entries); got != 1 {
- t.Errorf("want 1 module entry point; got %v", got)
- }
-
- // The imports slice should include import chains:
- // x -> avuln -> w -> bvuln
- // |
- // y ---->
- // That is, z package shoud not appear in the slice.
- wantImports := map[string][]string{
- "golang.org/entry/x": {"golang.org/amod/avuln"},
- "golang.org/entry/y": {"golang.org/amod/avuln"},
- "golang.org/amod/avuln": {"golang.org/wmod/w"},
- "golang.org/wmod/w": {"golang.org/bmod/bvuln"},
- }
-
- if igStrMap := impGraphToStrMap(result.Imports); !reflect.DeepEqual(wantImports, igStrMap) {
- t.Errorf("want %v imports graph; got %v", wantImports, igStrMap)
- }
-
- // The requires slice should include requires chains:
- // entry -> amod -> wmod -> bmod
- // That is, zmod module shoud not appear in the slice.
- wantRequires := map[string][]string{
- "golang.org/entry": {"golang.org/amod"},
- "golang.org/amod": {"golang.org/wmod"},
- "golang.org/wmod": {"golang.org/bmod"},
- }
-
- if rgStrMap := reqGraphToStrMap(result.Requires); !reflect.DeepEqual(wantRequires, rgStrMap) {
- t.Errorf("want %v requires graph; got %v", wantRequires, rgStrMap)
- }
-}
-
-// TestCallGraph checks for call graph vuln slicing correctness.
-// The inlined test code has the following call graph
-//
-// x.X
-// / | \
-// / d.D1 avuln.VulnData.Vuln1
-// / / |
-// c.C1 d.internal.Vuln1
-// |
-// avuln.VulnData.Vuln2
-//
-// --------------------y.Y-------------------------------
-// / / \ \ \ \
-// / / \ \ \ \
-// / / \ \ \ \
-// c.C4 c.vulnWrap.V.Vuln1(=nil) c.C2 bvuln.Vuln c.C3 c.C3$1
-// | | |
-// y.benign e.E
-//
-// and this slice
-//
-// x.X
-// / | \
-// / d.D1 avuln.VulnData.Vuln1
-// / /
-// c.C1
-// |
-// avuln.VulnData.Vuln2
-//
-// y.Y
-// |
-// bvuln.Vuln
-// | |
-// e.E
-// related to avuln.VulnData.{Vuln1, Vuln2} and bvuln.Vuln vulnerabilities.
-func TestCallGraph(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "x/x.go": `
- package x
-
- import (
- "golang.org/cmod/c"
- "golang.org/dmod/d"
- )
-
- func X(x bool) {
- if x {
- c.C1().Vuln1() // vuln use: Vuln1
- } else {
- d.D1() // no vuln use
- }
- }
- `,
- "y/y.go": `
- package y
-
- import (
- "golang.org/cmod/c"
- )
-
- func Y(y bool) {
- if y {
- c.C2()() // vuln use: bvuln.Vuln
- } else {
- c.C3()()
- w := c.C4(benign)
- w.V.Vuln1() // no vuln use: Vuln1 does not belong to vulnerable type
- }
- }
-
- func benign(i c.I) {}
- `}},
- {
- Name: "golang.org/cm...@v1.1.3",
- Files: map[string]interface{}{"c/c.go": `
- package c
-
- import (
- "golang.org/amod/avuln"
- "golang.org/bmod/bvuln"
- )
-
- type I interface {
- Vuln1()
- }
-
- func C1() I {
- v := avuln.VulnData{}
- v.Vuln2() // vuln use
- return v
- }
-
- func C2() func() {
- return bvuln.Vuln
- }
-
- func C3() func() {
- return func() {}
- }
-
- type vulnWrap struct {
- V I
- }
-
- func C4(f func(i I)) vulnWrap {
- f(avuln.VulnData{})
- return vulnWrap{}
- }
- `},
- },
- {
- Name: "golang.org/dm...@v0.5.0",
- Files: map[string]interface{}{"d/d.go": `
- package d
-
- import (
- "golang.org/cmod/c"
- )
-
- type internal struct{}
-
- func (i internal) Vuln1() {}
-
- func D1() {
- c.C1() // transitive vuln use
- var i c.I
- i = internal{}
- i.Vuln1() // no vuln use
- }
- `},
- },
- {
- Name: "golang.org/am...@v1.1.3",
- Files: map[string]interface{}{"avuln/avuln.go": `
- package avuln
-
- type VulnData struct {}
- func (v VulnData) Vuln1() {}
- func (v VulnData) Vuln2() {}
- `},
- },
- {
- Name: "golang.org/bm...@v0.5.0",
- Files: map[string]interface{}{"bvuln/bvuln.go": `
- package bvuln
-
- import (
- "golang.org/emod/e"
- )
-
- func Vuln() {
- e.E(Vuln)
- }
- `},
- },
- {
- Name: "golang.org/em...@v1.5.0",
- Files: map[string]interface{}{"e/e.go": `
- package e
-
- func E(f func()) {
- f()
- }
- `},
- },
- })
- defer e.Cleanup()
-
- // Load x and y as entry packages.
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"), path.Join(e.Temp(), "entry/y"))
- if err != nil {
- t.Fatal(err)
- }
-
- if len(pkgs) != 2 {
- t.Fatal("failed to load x and y test packages")
- }
-
- cfg := &Config{
- Client: testClient,
- }
- result, err := Source(context.Background(), Convert(pkgs), cfg)
- if err != nil {
- t.Fatal(err)
- }
-
- // Check that we find the right number of vulnerabilities.
- // There should be three entries as there are three vulnerable
- // symbols in the two import-reachable OSVs.
- if len(result.Vulns) != 3 {
- t.Errorf("want 3 Vulns, got %d", len(result.Vulns))
- }
-
- // Check that call graph entry points are present.
- if got := len(result.Calls.Entries); got != 2 {
- t.Errorf("want 2 call graph entry points; got %v", got)
- }
-
- // Check that vulnerabilities are connected to the call graph.
- // For the test example, all vulns should have a call sink.
- for _, v := range result.Vulns {
- if v.CallSink == 0 {
- t.Errorf("want CallSink !=0 for %v:%v; got 0", v.Symbol, v.PkgPath)
- }
- }
-
- wantCalls := map[string][]string{
- "golang.org/entry/x.X": {"golang.org/amod/avuln.VulnData.Vuln1", "golang.org/cmod/c.C1", "golang.org/dmod/d.D1"},
- "golang.org/cmod/c.C1": {"golang.org/amod/avuln.VulnData.Vuln2"},
- "golang.org/dmod/d.D1": {"golang.org/cmod/c.C1"},
- "golang.org/entry/y.Y": {"golang.org/bmod/bvuln.Vuln"},
- "golang.org/bmod/bvuln.Vuln": {"golang.org/emod/e.E"},
- "golang.org/emod/e.E": {"golang.org/bmod/bvuln.Vuln"},
- }
-
- if callStrMap := callGraphToStrMap(result.Calls); !reflect.DeepEqual(wantCalls, callStrMap) {
- t.Errorf("want %v call graph; got %v", wantCalls, callStrMap)
- }
-}
-
-func TestFiltering(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "x/x.go": `
- package x
-
- import "golang.org/vmod/vuln"
-
- func X() {
- vuln.V()
- }`,
- },
- },
- {
- Name: "golang.org/vm...@v1.2.3",
- Files: map[string]interface{}{"vuln/vuln.go": `
- package vuln
-
- func V() {}
- `},
- },
- })
- defer e.Cleanup()
-
- client := &mockClient{
- ret: map[string][]*osv.Entry{
- "golang.org/vmod": []*osv.Entry{
- {
- ID: "V",
- Affected: []osv.Affected{{
- Package: osv.Package{Name: "golang.org/vmod/vuln"},
- Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.2.0"}}}},
- EcosystemSpecific: osv.EcosystemSpecific{
- Symbols: []string{"V"},
- GOOS: []string{"linux"},
- GOARCH: []string{"amd64"},
- },
- }},
- },
- },
- },
- }
-
- // Load x as entry package.
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"))
- if err != nil {
- t.Fatal(err)
- }
- if len(pkgs) != 1 {
- t.Fatal("failed to load x test package")
- }
-
- cfg := &Config{
- Client: client,
- ImportsOnly: true,
- }
-
- os.Setenv("GOOS", "linux")
- os.Setenv("GOARCH", "amd64")
-
- result, err := Source(context.Background(), Convert(pkgs), cfg)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(result.Vulns) != 1 {
- t.Errorf("want 1 Vuln, got %d", len(result.Vulns))
- }
-
- os.Setenv("GOOS", "freebsd")
- os.Setenv("GOARCH", "arm64")
-
- result, err = Source(context.Background(), Convert(pkgs), cfg)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(result.Vulns) != 0 {
- t.Errorf("want 0 Vulns, got %d", len(result.Vulns))
- }
-}
-
-func TestAllSymbolsVulnerable(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "x/x.go": `
- package x
-
- import "golang.org/vmod/vuln"
-
- func X() {
- vuln.V1()
- }`,
- },
- },
- {
- Name: "golang.org/vm...@v1.2.3",
- Files: map[string]interface{}{"vuln/vuln.go": `
- package vuln
-
- func V1() {}
- func V2() {}
- func v() {}
- type a struct{}
- func (x a) foo() {}
- func (x *a) bar() {}
- `},
- },
- })
- defer e.Cleanup()
-
- client := &mockClient{
- ret: map[string][]*osv.Entry{
- "golang.org/vmod": []*osv.Entry{
- {
- ID: "V",
- Affected: []osv.Affected{{
- Package: osv.Package{Name: "golang.org/vmod/vuln"},
- Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.2.0"}}}},
- EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{}},
- }},
- },
- },
- },
- }
-
- // Load x as entry package.
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"))
- if err != nil {
- t.Fatal(err)
- }
- if len(pkgs) != 1 {
- t.Fatal("failed to load x test package")
- }
-
- cfg := &Config{
- Client: client,
- }
- result, err := Source(context.Background(), Convert(pkgs), cfg)
- if err != nil {
- t.Fatal(err)
- }
-
- if len(result.Vulns) != 5 {
- t.Errorf("want 5 Vulns, got %d", len(result.Vulns))
- }
-
- for _, v := range result.Vulns {
- if v.Symbol == "V1" && v.CallSink == 0 {
- t.Errorf("expected a call sink for V1; got none")
- } else if v.Symbol != "V1" && v.CallSink != 0 {
- t.Errorf("expected no call sink for %v; got %v", v.Symbol, v.CallSink)
- }
- }
-}
diff --git a/vulncheck/tools_test.go b/vulncheck/tools_test.go
deleted file mode 100644
index 3c9b1d6..0000000
--- a/vulncheck/tools_test.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2021 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 tools
-// +build tools
-
-package main
-
-import (
- _ "github.com/client9/misspell/cmd/misspell"
- _ "honnef.co/go/tools/cmd/staticcheck"
- _ "mvdan.cc/unparam"
-)
diff --git a/vulncheck/utils.go b/vulncheck/utils.go
deleted file mode 100644
index 780cd63..0000000
--- a/vulncheck/utils.go
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "bytes"
- "go/token"
- "go/types"
- "os"
- "strings"
-
- "golang.org/x/tools/go/callgraph"
- "golang.org/x/tools/go/callgraph/cha"
- "golang.org/x/tools/go/callgraph/vta"
- "golang.org/x/tools/go/ssa/ssautil"
- "golang.org/x/tools/go/types/typeutil"
-
- "golang.org/x/tools/go/ssa"
-)
-
-// buildSSA creates an ssa representation for pkgs. Returns
-// the ssa program encapsulating the packages and top level
-// ssa packages corresponding to pkgs.
-func buildSSA(pkgs []*Package, fset *token.FileSet) (*ssa.Program, []*ssa.Package) {
- prog := ssa.NewProgram(fset, ssa.BuilderMode(0))
-
- imports := make(map[*Package]*ssa.Package)
- var createImports func([]*Package)
- createImports = func(pkgs []*Package) {
- for _, p := range pkgs {
- if _, ok := imports[p]; !ok {
- i := prog.CreatePackage(p.Pkg, p.Syntax, p.TypesInfo, true)
- imports[p] = i
- createImports(p.Imports)
- }
- }
- }
-
- for _, tp := range pkgs {
- createImports(tp.Imports)
- }
-
- var ssaPkgs []*ssa.Package
- for _, tp := range pkgs {
- if sp, ok := imports[tp]; ok {
- ssaPkgs = append(ssaPkgs, sp)
- } else {
- sp := prog.CreatePackage(tp.Pkg, tp.Syntax, tp.TypesInfo, false)
- ssaPkgs = append(ssaPkgs, sp)
- }
- }
- prog.Build()
- return prog, ssaPkgs
-}
-
-// callGraph builds a call graph of prog based on VTA analysis.
-func callGraph(prog *ssa.Program, entries []*ssa.Function) *callgraph.Graph {
- entrySlice := make(map[*ssa.Function]bool)
- for _, e := range entries {
- entrySlice[e] = true
- }
- initial := cha.CallGraph(prog)
- allFuncs := ssautil.AllFunctions(prog)
-
- fslice := forwardReachableFrom(entrySlice, initial)
- // Keep only actually linked functions.
- pruneSet(fslice, allFuncs)
- vtaCg := vta.CallGraph(fslice, initial)
-
- // Repeat the process once more, this time using
- // the produced VTA call graph as the base graph.
- fslice = forwardReachableFrom(entrySlice, vtaCg)
- pruneSet(fslice, allFuncs)
-
- return vta.CallGraph(fslice, vtaCg)
-}
-
-// siteCallees computes a set of callees for call site `call` given program `callgraph`.
-func siteCallees(call ssa.CallInstruction, callgraph *callgraph.Graph) []*ssa.Function {
- var matches []*ssa.Function
-
- node := callgraph.Nodes[call.Parent()]
- if node == nil {
- return nil
- }
-
- for _, edge := range node.Out {
- // Some callgraph analyses, such as CHA, might return synthetic (interface)
- // methods as well as the concrete methods. Skip such synthetic functions.
- if edge.Site == call {
- matches = append(matches, edge.Callee.Func)
- }
- }
- return matches
-}
-
-// dbTypeFormat formats the name of t according how types
-// are encoded in vulnerability database:
-// - pointer designation * is skipped
-// - full path prefix is skipped as well
-func dbTypeFormat(t types.Type) string {
- switch tt := t.(type) {
- case *types.Pointer:
- return dbTypeFormat(tt.Elem())
- case *types.Named:
- return tt.Obj().Name()
- default:
- return types.TypeString(t, func(p *types.Package) string { return "" })
- }
-}
-
-// dbFuncName computes a function name consistent with the namings used in vulnerability
-// databases. Effectively, a qualified name of a function local to its enclosing package.
-// If a receiver is a pointer, this information is not encoded in the resulting name. The
-// name of anonymous functions is simply "". The function names are unique subject to the
-// enclosing package, but not globally.
-//
-// Examples:
-// func (a A) foo (...) {...} -> A.foo
-// func foo(...) {...} -> foo
-// func (b *B) bar (...) {...} -> B.bar
-func dbFuncName(f *ssa.Function) string {
- selectBound := func(f *ssa.Function) types.Type {
- // If f is a "bound" function introduced by ssa for a given type, return the type.
- // When "f" is a "bound" function, it will have 1 free variable of that type within
- // the function. This is subject to change when ssa changes.
- if len(f.FreeVars) == 1 && strings.HasPrefix(f.Synthetic, "bound ") {
- return f.FreeVars[0].Type()
- }
- return nil
- }
- selectThunk := func(f *ssa.Function) types.Type {
- // If f is a "thunk" function introduced by ssa for a given type, return the type.
- // When "f" is a "thunk" function, the first parameter will have that type within
- // the function. This is subject to change when ssa changes.
- params := f.Signature.Params() // params.Len() == 1 then params != nil.
- if strings.HasPrefix(f.Synthetic, "thunk ") && params.Len() >= 1 {
- if first := params.At(0); first != nil {
- return first.Type()
- }
- }
- return nil
- }
- var qprefix string
- if recv := f.Signature.Recv(); recv != nil {
- qprefix = dbTypeFormat(recv.Type())
- } else if btype := selectBound(f); btype != nil {
- qprefix = dbTypeFormat(btype)
- } else if ttype := selectThunk(f); ttype != nil {
- qprefix = dbTypeFormat(ttype)
- }
-
- if qprefix == "" {
- return f.Name()
- }
- return qprefix + "." + f.Name()
-}
-
-// dbTypesFuncName is dbFuncName defined over *types.Func.
-func dbTypesFuncName(f *types.Func) string {
- sig := f.Type().(*types.Signature)
- if sig.Recv() == nil {
- return f.Name()
- }
- return dbTypeFormat(sig.Recv().Type()) + "." + f.Name()
-}
-
-// memberFuncs returns functions associated with the `member`:
-// 1) `member` itself if `member` is a function
-// 2) `member` methods if `member` is a type
-// 3) empty list otherwise
-func memberFuncs(member ssa.Member, prog *ssa.Program) []*ssa.Function {
- switch t := member.(type) {
- case *ssa.Type:
- methods := typeutil.IntuitiveMethodSet(t.Type(), &prog.MethodSets)
- var funcs []*ssa.Function
- for _, m := range methods {
- if f := prog.MethodValue(m); f != nil {
- funcs = append(funcs, f)
- }
- }
- return funcs
- case *ssa.Function:
- return []*ssa.Function{t}
- default:
- return nil
- }
-}
-
-// funcPosition gives the position of `f`. Returns empty token.Position
-// if no file information on `f` is available.
-func funcPosition(f *ssa.Function) *token.Position {
- pos := f.Prog.Fset.Position(f.Pos())
- return &pos
-}
-
-// instrPosition gives the position of `instr`. Returns empty token.Position
-// if no file information on `instr` is available.
-func instrPosition(instr ssa.Instruction) *token.Position {
- pos := instr.Parent().Prog.Fset.Position(instr.Pos())
- return &pos
-}
-
-func resolved(call ssa.CallInstruction) bool {
- if call == nil {
- return true
- }
- return call.Common().StaticCallee() != nil
-}
-
-func callRecvType(call ssa.CallInstruction) string {
- if !call.Common().IsInvoke() {
- return ""
- }
- buf := new(bytes.Buffer)
- types.WriteType(buf, call.Common().Value.Type(), nil)
- return buf.String()
-}
-
-func funcRecvType(f *ssa.Function) string {
- v := f.Signature.Recv()
- if v == nil {
- return ""
- }
- buf := new(bytes.Buffer)
- types.WriteType(buf, v.Type(), nil)
- return buf.String()
-}
-
-func lookupEnv(key, defaultValue string) string {
- if v, ok := os.LookupEnv(key); ok {
- return v
- }
- return defaultValue
-}
-
-// allSymbols returns all top-level functions and methods defined in pkg.
-func allSymbols(pkg *types.Package) []string {
- var names []string
- scope := pkg.Scope()
- for _, name := range scope.Names() {
- o := scope.Lookup(name)
- switch o := o.(type) {
- case *types.Func:
- names = append(names, dbTypesFuncName(o))
- case *types.TypeName:
- ms := types.NewMethodSet(types.NewPointer(o.Type()))
- for i := 0; i < ms.Len(); i++ {
- if f, ok := ms.At(i).Obj().(*types.Func); ok {
- names = append(names, dbTypesFuncName(f))
- }
- }
- }
- }
- return names
-}
diff --git a/vulncheck/vulncheck.go b/vulncheck/vulncheck.go
deleted file mode 100644
index 8025ca4..0000000
--- a/vulncheck/vulncheck.go
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright 2021 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.
-
-// Package vulncheck detects uses of known vulnerabilities
-// in Go binaries and source code.
-package vulncheck
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "go/types"
- "strings"
-
- "golang.org/x/tools/go/packages"
- "golang.org/x/vuln/client"
- "golang.org/x/vuln/osv"
-)
-
-// Config is used for configuring vulncheck algorithms.
-type Config struct {
- // ImportsOnly flag, if true, signals vulncheck to analyze import chains only.
- // Otherwise, call chains are analyzed too.
- ImportsOnly bool
- // Client is used for querying data from a vulnerability database.
- Client client.Client
-}
-
-// Package models Go package for vulncheck analysis. A version
-// of packages.Package trimmed down to reduce memory consumption.
-type Package struct {
- Name string
- PkgPath string
- Imports []*Package
- Pkg *types.Package
- Fset *token.FileSet
- Syntax []*ast.File
- TypesInfo *types.Info
- Module *Module
-}
-
-// Module models Go module for vulncheck analysis.
-type Module struct {
- Path string
- Version string
- Dir string
- Replace *Module
-}
-
-// Convert converts a slice of packages.Package to
-// a slice of corresponding vulncheck.Package.
-func Convert(pkgs []*packages.Package) []*Package {
- ms := make(map[*packages.Module]*Module)
- var mod func(*packages.Module) *Module
- mod = func(m *packages.Module) *Module {
- if m == nil {
- return nil
- }
- if vm, ok := ms[m]; ok {
- return vm
- }
- vm := &Module{
- Path: m.Path,
- Version: m.Version,
- Dir: m.Dir,
- Replace: mod(m.Replace),
- }
- ms[m] = vm
- return vm
- }
-
- ps := make(map[*packages.Package]*Package)
- var pkg func(*packages.Package) *Package
- pkg = func(p *packages.Package) *Package {
- if vp, ok := ps[p]; ok {
- return vp
- }
-
- vp := &Package{
- Name: p.Name,
- PkgPath: p.PkgPath,
- Pkg: p.Types,
- Fset: p.Fset,
- Syntax: p.Syntax,
- TypesInfo: p.TypesInfo,
- Module: mod(p.Module),
- }
- ps[p] = vp
-
- for _, i := range p.Imports {
- vp.Imports = append(vp.Imports, pkg(i))
- }
- return vp
- }
-
- var vpkgs []*Package
- for _, p := range pkgs {
- vpkgs = append(vpkgs, pkg(p))
- }
- return vpkgs
-}
-
-// Result contains information on which vulnerabilities are potentially affecting
-// user code and how are they affecting it via call graph, package imports graph,
-// and module requires graph.
-type Result struct {
- // Calls is a call graph whose roots are program entry functions/methods and
- // sinks are vulnerable functions/methods. Empty when Config.ImportsOnly=true
- // or when no vulnerable symbols are reachable via program call graph.
- Calls *CallGraph
- // Imports is a package dependency graph whose roots are entry user packages
- // and sinks are the packages with some vulnerable symbols. Empty when no
- // packages with some vulnerabilities are imported in the program.
- Imports *ImportGraph
- // Requires is a module dependency graph whose roots are entry user modules
- // and sinks are modules with some vulnerable packages. Empty when no modules
- // with some vulnerabilities are required by the program.
- Requires *RequireGraph
-
- // Vulns contains information on detected vulnerabilities and their place in
- // the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
- // or whose packages are imported in Imports, or whose modules are required in
- // Requires, have an entry in Vulns.
- Vulns []*Vuln
-}
-
-// Vuln provides information on how a vulnerability is affecting user code by
-// connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities
-// detected in Go binaries do not have a place in the Result graphs.
-type Vuln struct {
- // The next four fields identify a vulnerability. Note that *osv.Entry
- // describes potentially multiple symbols from multiple packages.
-
- // OSV contains information on detected vulnerability in the shared
- // vulnerability format.
- OSV *osv.Entry
- // Symbol is the name of the detected vulnerable function or method.
- Symbol string
- // PkgPath is the package path of the detected Symbol.
- PkgPath string
- // ModPath is the module path corresponding to PkgPath.
- ModPath string
-
- // CallSink is the ID of the sink node in Calls graph corresponding to
- // the use of Symbol. ID is not available (denoted with 0) in binary mode,
- // or if Symbol is not reachable, or if Config.ImportsOnly=true.
- CallSink int
- // ImportSink is the ID of the sink node in the Imports graph corresponding
- // to the import of PkgPath. ID is not available (denoted with 0) in binary
- // mode or if PkgPath is not imported.
- ImportSink int
- // RequireSink is the ID of the sink node in Requires graph corresponding
- // to the require statement of ModPath. ID is not available (denoted with 0)
- // in binary mode.
- RequireSink int
-}
-
-// CallGraph is a slice of a full program call graph whose sinks are conceptually
-// vulnerable functions and sources are entry points of user packages. In order to
-// support succinct traversal of the slice related to a particular vulnerability,
-// CallGraph is technically backwards directed, i.e., from a vulnerable function
-// towards the program entry functions (see FuncNode).
-type CallGraph struct {
- // Functions contains all call graph nodes as a map: func node id -> func node.
- Functions map[int]*FuncNode
- // Entries are IDs of a subset of Functions representing vulncheck entry points.
- Entries []int
-}
-
-type FuncNode struct {
- ID int
- Name string
- // RecvType is the receiver object type of this function, if any.
- RecvType string
- PkgPath string
- Pos *token.Position
- // CallSites is a set of call sites where this function is called.
- CallSites []*CallSite
-}
-
-func (fn *FuncNode) String() string {
- if fn.RecvType == "" {
- return fmt.Sprintf("%s.%s", fn.PkgPath, fn.Name)
- }
- return fmt.Sprintf("%s.%s", fn.RecvType, fn.Name)
-}
-
-type CallSite struct {
- // Parent is ID of the enclosing function where the call is made.
- Parent int
- // Name stands for the name of the function (variable) being called.
- Name string
- // RecvType is the full path of the receiver object type, if any.
- RecvType string
- Pos *token.Position
- // Resolved indicates if the called function can be statically resolved.
- Resolved bool
-}
-
-// RequireGraph is a slice of a full program module requires graph whose sinks
-// are conceptually modules with some known vulnerabilities and sources are modules
-// of user entry packages. In order to support succinct traversal of the slice
-// related to a particular vulnerability, RequireGraph is technically backwards
-// directed, i.e., from a vulnerable module towards the program entry modules (see ModNode).
-type RequireGraph struct {
- // Modules contains all module nodes as a map: module node id -> module node.
- Modules map[int]*ModNode
- // Entries are IDs of a subset of Modules representing modules of vulncheck entry points.
- Entries []int
-}
-
-type ModNode struct {
- ID int
- Path string
- Version string
- // Replace is the ID of the replacement module node, if any.
- Replace int
- // RequiredBy contains IDs of the modules requiring this module.
- RequiredBy []int
-}
-
-// ImportGraph is a slice of a full program package import graph whose sinks are
-// conceptually packages with some known vulnerabilities and sources are user
-// specified packages. In order to support succinct traversal of the slice related
-// to a particular vulnerability, ImportGraph is technically backwards directed,
-// i.e., from a vulnerable package towards the program entry packages (see PkgNode).
-type ImportGraph struct {
- // Packages contains all package nodes as a map: package node id -> package node.
- Packages map[int]*PkgNode
- // Entries are IDs of a subset of Packages representing packages of vulncheck entry points.
- Entries []int
-}
-
-type PkgNode struct {
- ID int
- // Name is the package identifier as it appears in the source code.
- Name string
- Path string
- // Module holds ID of the corresponding module (node) in Requires graph.
- Module int
- // ImportedBy contains IDs of packages directly importing this package.
- ImportedBy []int
-
- // pkg is used for connecting package node to module and call graph nodes.
- pkg *Package
-}
-
-// moduleVulnerabilities is an internal structure for
-// holding and querying vulnerabilities provided by a
-// vulnerability database client.
-type moduleVulnerabilities []modVulns
-
-// modVulns groups vulnerabilities per module.
-type modVulns struct {
- mod *Module
- vulns []*osv.Entry
-}
-
-func (mv moduleVulnerabilities) Filter(os, arch string) moduleVulnerabilities {
- var filteredMod moduleVulnerabilities
- for _, mod := range mv {
- module := mod.mod
- modVersion := module.Version
- if module.Replace != nil {
- modVersion = module.Replace.Version
- }
- // TODO(https://golang.org/issues/49264): if modVersion == "", try vcs?
- var filteredVulns []*osv.Entry
- for _, v := range mod.vulns {
- var filteredAffected []osv.Affected
- for _, a := range v.Affected {
- // A module version is affected if
- // - it is included in one of the affected version ranges
- // - and module version is not ""
- // The latter means the module version is not available, so
- // we don't want to spam users with potential false alarms.
- // TODO: issue warning for "" cases above?
- affected := modVersion != "" && a.Ranges.AffectsSemver(modVersion) && matchesPlatform(os, arch, a.EcosystemSpecific)
- if affected {
- filteredAffected = append(filteredAffected, a)
- }
- }
- if len(filteredAffected) == 0 {
- continue
- }
- // save the non-empty vulnerability with only
- // affected symbols.
- newV := *v
- newV.Affected = filteredAffected
- filteredVulns = append(filteredVulns, &newV)
- }
- filteredMod = append(filteredMod, modVulns{
- mod: module,
- vulns: filteredVulns,
- })
- }
- return filteredMod
-}
-
-func matchesPlatform(os, arch string, e osv.EcosystemSpecific) bool {
- matchesOS := len(e.GOOS) == 0
- matchesArch := len(e.GOARCH) == 0
- for _, o := range e.GOOS {
- if os == o {
- matchesOS = true
- break
- }
- }
- for _, a := range e.GOARCH {
- if arch == a {
- matchesArch = true
- break
- }
- }
- return matchesOS && matchesArch
-}
-func (mv moduleVulnerabilities) Num() int {
- var num int
- for _, m := range mv {
- num += len(m.vulns)
- }
- return num
-}
-
-// VulnsForPackage returns the vulnerabilities for the module which is the most
-// specific prefix of importPath, or nil if there is no matching module with
-// vulnerabilities.
-func (mv moduleVulnerabilities) VulnsForPackage(importPath string) []*osv.Entry {
- var mostSpecificMod *modVulns
- for _, mod := range mv {
- md := mod
- if strings.HasPrefix(importPath, md.mod.Path) {
- if mostSpecificMod == nil || len(mostSpecificMod.mod.Path) < len(md.mod.Path) {
- mostSpecificMod = &md
- }
- }
- }
-
- if mostSpecificMod == nil {
- return nil
- }
-
- if mostSpecificMod.mod.Replace != nil {
- importPath = fmt.Sprintf("%s%s", mostSpecificMod.mod.Replace.Path, strings.TrimPrefix(importPath, mostSpecificMod.mod.Path))
- }
- vulns := mostSpecificMod.vulns
- packageVulns := []*osv.Entry{}
- for _, v := range vulns {
- for _, a := range v.Affected {
- if a.Package.Name == importPath {
- packageVulns = append(packageVulns, v)
- break
- }
- }
- }
- return packageVulns
-}
-
-// VulnsForSymbol returns vulnerabilities for `symbol` in `mv.VulnsForPackage(importPath)`.
-func (mv moduleVulnerabilities) VulnsForSymbol(importPath, symbol string) []*osv.Entry {
- vulns := mv.VulnsForPackage(importPath)
- if vulns == nil {
- return nil
- }
-
- symbolVulns := []*osv.Entry{}
- for _, v := range vulns {
- vulnLoop:
- for _, a := range v.Affected {
- if a.Package.Name != importPath {
- continue
- }
- if len(a.EcosystemSpecific.Symbols) == 0 {
- symbolVulns = append(symbolVulns, v)
- continue vulnLoop
- }
- for _, s := range a.EcosystemSpecific.Symbols {
- if s == symbol {
- symbolVulns = append(symbolVulns, v)
- continue vulnLoop
- }
- }
- }
- }
- return symbolVulns
-}
-
-// Vulns returns vulnerabilities for all modules in `mv`.
-func (mv moduleVulnerabilities) Vulns() []*osv.Entry {
- var vulns []*osv.Entry
- seen := make(map[string]bool)
- for _, mv := range mv {
- for _, v := range mv.vulns {
- if !seen[v.ID] {
- vulns = append(vulns, v)
- seen[v.ID] = true
- }
- }
- }
- return vulns
-}
diff --git a/vulncheck/vulncheck_test.go b/vulncheck/vulncheck_test.go
deleted file mode 100644
index 9faf00e..0000000
--- a/vulncheck/vulncheck_test.go
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "path"
- "reflect"
- "testing"
-
- "golang.org/x/tools/go/packages/packagestest"
- "golang.org/x/vuln/osv"
-)
-
-func TestFilterVulns(t *testing.T) {
- mv := moduleVulnerabilities{
- {
- mod: &Module{
- Path: "example.mod/a",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{
- {Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}},
- {Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "1.0.0"}}}}}, // should be filtered out
- }},
- {ID: "b", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows", "linux"}}}}},
- {ID: "c", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.1"}}}}, EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64", "amd64"}}}}},
- {ID: "d", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/b",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "e", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64"}}}}},
- {ID: "f", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
- {ID: "g", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.1"}, {Fixed: "2.0.1"}}}}}}},
- {ID: "h", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}, GOARCH: []string{"amd64"}}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/c",
- },
- vulns: []*osv.Entry{
- {ID: "i", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.0"}}}}}}},
- {ID: "j", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "3.0.0"}}}}}}},
- {ID: "k"},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/d",
- Version: "v1.2.0",
- },
- vulns: []*osv.Entry{
- {ID: "l", Affected: []osv.Affected{
- {EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"windows"}}}, // should be filtered out
- {EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}},
- }},
- },
- },
- }
-
- expected := moduleVulnerabilities{
- {
- mod: &Module{
- Path: "example.mod/a",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{{Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Fixed: "2.0.0"}}}}}}},
- {ID: "c", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"arm64", "amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.1"}, {Fixed: "1.0.1"}}}}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/b",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "f", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
- {ID: "g", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOARCH: []string{"amd64"}}, Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "0.0.1"}, {Fixed: "2.0.1"}}}}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/c",
- },
- },
- {
- mod: &Module{
- Path: "example.mod/d",
- Version: "v1.2.0",
- },
- vulns: []*osv.Entry{
- {ID: "l", Affected: []osv.Affected{{EcosystemSpecific: osv.EcosystemSpecific{GOOS: []string{"linux"}}}}},
- },
- },
- }
-
- filtered := mv.Filter("linux", "amd64")
- if !reflect.DeepEqual(filtered, expected) {
- t.Fatalf("Filter returned unexpected results, got:\n%s\nwant:\n%s", moduleVulnerabilitiesToString(filtered), moduleVulnerabilitiesToString(expected))
- }
-}
-
-func TestVulnsForPackage(t *testing.T) {
- mv := moduleVulnerabilities{
- {
- mod: &Module{
- Path: "example.mod/a",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/a/b",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/d",
- Version: "v0.0.1",
- },
- vulns: []*osv.Entry{
- {ID: "d", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/d"}}}},
- },
- },
- }
-
- filtered := mv.VulnsForPackage("example.mod/a/b/c")
- expected := []*osv.Entry{
- {ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
- }
-
- if !reflect.DeepEqual(filtered, expected) {
- t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
- }
-}
-
-func TestVulnsForPackageReplaced(t *testing.T) {
- mv := moduleVulnerabilities{
- {
- mod: &Module{
- Path: "example.mod/a",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/a/b",
- Replace: &Module{
- Path: "example.mod/b",
- },
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b/c"}}}},
- },
- },
- }
-
- filtered := mv.VulnsForPackage("example.mod/a/b/c")
- expected := []*osv.Entry{
- {ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/b/c"}}}},
- }
-
- if !reflect.DeepEqual(filtered, expected) {
- t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
- }
-}
-
-func TestVulnsForSymbol(t *testing.T) {
- mv := moduleVulnerabilities{
- {
- mod: &Module{
- Path: "example.mod/a",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "a", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}}}},
- },
- },
- {
- mod: &Module{
- Path: "example.mod/a/b",
- Version: "v1.0.0",
- },
- vulns: []*osv.Entry{
- {ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"a"}}}}},
- {ID: "c", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"b"}}}}},
- },
- },
- }
-
- filtered := mv.VulnsForSymbol("example.mod/a/b/c", "a")
- expected := []*osv.Entry{
- {ID: "b", Affected: []osv.Affected{{Package: osv.Package{Name: "example.mod/a/b/c"}, EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"a"}}}}},
- }
-
- if !reflect.DeepEqual(filtered, expected) {
- t.Fatalf("VulnsForPackage returned unexpected results, got:\n%s\nwant:\n%s", vulnsToString(filtered), vulnsToString(expected))
- }
-}
-
-func TestConvert(t *testing.T) {
- e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
- {
- Name: "golang.org/entry",
- Files: map[string]interface{}{
- "x/x.go": `
- package x
-
- import "golang.org/amod/avuln"
- `}},
- {
- Name: "golang.org/zm...@v0.0.0",
- Files: map[string]interface{}{"z/z.go": `
- package z
- `},
- },
- {
- Name: "golang.org/am...@v1.1.3",
- Files: map[string]interface{}{"avuln/avuln.go": `
- package avuln
-
- import "golang.org/wmod/w"
- `},
- },
- {
- Name: "golang.org/bm...@v0.5.0",
- Files: map[string]interface{}{"bvuln/bvuln.go": `
- package bvuln
- `},
- },
- {
- Name: "golang.org/wm...@v0.0.0",
- Files: map[string]interface{}{"w/w.go": `
- package w
-
- import "golang.org/bmod/bvuln"
- `},
- },
- })
- defer e.Cleanup()
-
- // Load x and y as entry packages.
- pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"), path.Join(e.Temp(), "entry/y"))
- if err != nil {
- t.Fatal(err)
- }
-
- vpkgs := Convert(pkgs)
-
- wantPkgs := map[string][]string{
- "golang.org/amod/avuln": {"golang.org/wmod/w"},
- "golang.org/bmod/bvuln": nil,
- "golang.org/entry/x": {"golang.org/amod/avuln"},
- "golang.org/entry/y": nil,
- "golang.org/wmod/w": {"golang.org/bmod/bvuln"},
- }
- if got := pkgPathToImports(vpkgs); !reflect.DeepEqual(got, wantPkgs) {
- t.Errorf("want %v;got %v", wantPkgs, got)
- }
-
- wantMods := map[string]string{
- "golang.org/amod": "v1.1.3",
- "golang.org/bmod": "v0.5.0",
- "golang.org/entry": "",
- "golang.org/wmod": "v0.0.0",
- }
- if got := modulePathToVersion(vpkgs); !reflect.DeepEqual(got, wantMods) {
- t.Errorf("want %v;got %v", wantMods, got)
- }
-}
diff --git a/vulncheck/witness.go b/vulncheck/witness.go
deleted file mode 100644
index 57c74ca..0000000
--- a/vulncheck/witness.go
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "container/list"
- "fmt"
- "sort"
- "strings"
- "sync"
-)
-
-// ImportChain is sequence of import paths starting with
-// a client package and ending with a package with some
-// known vulnerabilities.
-type ImportChain []*PkgNode
-
-// ImportChains lists import chains for each vulnerability in res. The
-// reported chains are ordered by how seemingly easy is to understand
-// them. Shorter import chains appear earlier in the returned slices.
-//
-// ImportChains does not list all import chains for a vulnerability.
-// It performs a BFS search of res.RequireGraph starting at a vulnerable
-// package and going up until reaching an entry package in res.ImportGraph.Entries.
-// During this search, a package is visited only once to avoid analyzing
-// every possible import chain.
-//
-// Note that the resulting map produces an import chain for each Vuln. Vulns
-// with the same PkgPath will have the same list of identified import chains.
-func ImportChains(res *Result) map[*Vuln][]ImportChain {
- // Group vulns per package.
- vPerPkg := make(map[int][]*Vuln)
- for _, v := range res.Vulns {
- vPerPkg[v.ImportSink] = append(vPerPkg[v.ImportSink], v)
- }
-
- // Collect chains in parallel for every package path.
- var wg sync.WaitGroup
- var mu sync.Mutex
- chains := make(map[*Vuln][]ImportChain)
- for pkgID, vulns := range vPerPkg {
- pID := pkgID
- vs := vulns
- wg.Add(1)
- go func() {
- pChains := importChains(pID, res)
- mu.Lock()
- for _, v := range vs {
- chains[v] = pChains
- }
- mu.Unlock()
- wg.Done()
- }()
- }
- wg.Wait()
- return chains
-}
-
-// importChains finds representative chains of package imports
-// leading to vulnerable package identified with vulnSinkID.
-func importChains(vulnSinkID int, res *Result) []ImportChain {
- if vulnSinkID == 0 {
- return nil
- }
-
- // Entry packages, needed for finalizing chains.
- entries := make(map[int]bool)
- for _, e := range res.Imports.Entries {
- entries[e] = true
- }
-
- var chains []ImportChain
- seen := make(map[int]bool)
-
- queue := list.New()
- queue.PushBack(&importChain{pkg: res.Imports.Packages[vulnSinkID]})
- for queue.Len() > 0 {
- front := queue.Front()
- c := front.Value.(*importChain)
- queue.Remove(front)
-
- pkg := c.pkg
- if seen[pkg.ID] {
- continue
- }
- seen[pkg.ID] = true
-
- for _, impBy := range pkg.ImportedBy {
- imp := res.Imports.Packages[impBy]
- newC := &importChain{pkg: imp, child: c}
- // If the next package is an entry, we have
- // a chain to report.
- if entries[imp.ID] {
- chains = append(chains, newC.ImportChain())
- }
- queue.PushBack(newC)
- }
- }
- return chains
-}
-
-// importChain models an chain of package imports.
-type importChain struct {
- pkg *PkgNode
- child *importChain
-}
-
-// ImportChain converts importChain to ImportChain type.
-func (r *importChain) ImportChain() ImportChain {
- if r == nil {
- return nil
- }
- return append([]*PkgNode{r.pkg}, r.child.ImportChain()...)
-}
-
-// 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 {
- // Function provides information on the function whose frame is on the stack.
- Function *FuncNode
-
- // Call provides information on the call site inducing this stack frame.
- // nil when the frame represents an entry point of the stack.
- Call *CallSite
-}
-
-// CallStacks lists call stacks for each vulnerability in res. The listed call
-// stacks are ordered by how seemingly easy is to understand them. In general,
-// shorter call stacks with less dynamic call sites appear earlier in the returned
-// call stack slices.
-//
-// CallStacks does not report every possible call stack for a vulnerable symbol.
-// It performs a BFS search of res.CallGraph starting at the symbol and going up
-// until reaching an entry function or method in res.CallGraph.Entries. During
-// this search, each function is visited at most once to avoid potential
-// exponential explosion, thus skipping some call stacks.
-func CallStacks(res *Result) map[*Vuln][]CallStack {
- var (
- wg sync.WaitGroup
- mu sync.Mutex
- )
- stacksPerVuln := make(map[*Vuln][]CallStack)
- for _, vuln := range res.Vulns {
- vuln := vuln
- wg.Add(1)
- go func() {
- cs := callStacks(vuln.CallSink, res)
- // sort call stacks by the estimated value to the user
- sort.SliceStable(cs, func(i int, j int) bool { return stackLess(cs[i], cs[j]) })
- mu.Lock()
- stacksPerVuln[vuln] = cs
- mu.Unlock()
- wg.Done()
- }()
- }
-
- wg.Wait()
- return stacksPerVuln
-}
-
-// callStacks finds representative call stacks
-// for vulnerable symbol identified with vulnSinkID.
-func callStacks(vulnSinkID int, res *Result) []CallStack {
- if vulnSinkID == 0 {
- return nil
- }
-
- entries := make(map[int]bool)
- for _, e := range res.Calls.Entries {
- entries[e] = true
- }
-
- var stacks []CallStack
- seen := make(map[int]bool)
-
- queue := list.New()
- queue.PushBack(&callChain{f: res.Calls.Functions[vulnSinkID]})
-
- for queue.Len() > 0 {
- front := queue.Front()
- c := front.Value.(*callChain)
- queue.Remove(front)
-
- f := c.f
- if seen[f.ID] {
- continue
- }
- seen[f.ID] = true
-
- for _, cs := range f.CallSites {
- callee := res.Calls.Functions[cs.Parent]
- nStack := &callChain{f: callee, call: cs, child: c}
- if entries[callee.ID] {
- stacks = append(stacks, nStack.CallStack())
- }
- queue.PushBack(nStack)
- }
- }
- return stacks
-}
-
-// callChain models a chain of function calls.
-type callChain struct {
- call *CallSite // nil for entry points
- f *FuncNode
- child *callChain
-}
-
-// CallStack converts callChain to CallStack type.
-func (c *callChain) CallStack() CallStack {
- if c == nil {
- return nil
- }
- return append(CallStack{StackEntry{Function: c.f, Call: c.call}}, c.child.CallStack()...)
-}
-
-// weight computes an approximate measure of how easy is to understand the call
-// stack when presented to the client as a witness. The smaller the value, the more
-// understandable the stack is. Currently defined as the number of unresolved
-// call sites in the stack.
-func weight(stack CallStack) int {
- w := 0
- for _, e := range stack {
- if e.Call != nil && !e.Call.Resolved {
- w += 1
- }
- }
- return w
-}
-
-func isStdPackage(pkg string) bool {
- if pkg == "" {
- return false
- }
- // std packages do not have a "." in their path. For instance, see
- // Contains in pkgsite/+/refs/heads/master/internal/stdlbib/stdlib.go.
- if i := strings.IndexByte(pkg, '/'); i != -1 {
- pkg = pkg[:i]
- }
- return !strings.Contains(pkg, ".")
-}
-
-// confidence computes an approximate measure of whether the stack
-// is realizeable in practice. Currently, it equals the number of call
-// sites in stack that go through standard libraries. Such call stacks
-// have been experimentally shown to often result in false positives.
-func confidence(stack CallStack) int {
- c := 0
- for _, e := range stack {
- if isStdPackage(e.Function.PkgPath) {
- c += 1
- }
- }
- return c
-}
-
-// stackLess compares two call stacks in terms of their estimated
-// value to the user. Shorter stacks generally come earlier in the ordering.
-//
-// Two stacks are lexicographically ordered by:
-// 1) their estimated level of confidence in being a real call stack,
-// 2) their length, and 3) the number of dynamic call sites in the stack.
-func stackLess(s1, s2 CallStack) bool {
- if c1, c2 := confidence(s1), confidence(s2); c1 != c2 {
- return c1 < c2
- }
-
- if len(s1) != len(s2) {
- return len(s1) < len(s2)
- }
-
- if w1, w2 := weight(s1), weight(s2); w1 != w2 {
- return w1 < w2
- }
- // At this point we just need to make sure the ordering is deterministic.
- // TODO(zpavlinovic): is there a more meaningful additional ordering?
- return stackStrLess(s1, s2)
-}
-
-// stackStrLess compares string representation of stacks.
-func stackStrLess(s1, s2 CallStack) bool {
- // Creates a unique string representation of a call stack
- // for comparison purposes only.
- stackStr := func(stack CallStack) string {
- var stackStr []string
- for _, cs := range stack {
- s := cs.Function.String()
- if cs.Call != nil && cs.Call.Pos != nil {
- p := cs.Call.Pos
- s = fmt.Sprintf("%s[%s:%d:%d:%d]", s, p.Filename, p.Line, p.Column, p.Offset)
- }
- stackStr = append(stackStr, s)
- }
- return strings.Join(stackStr, "->")
- }
- return strings.Compare(stackStr(s1), stackStr(s2)) <= 0
-}
diff --git a/vulncheck/witness_test.go b/vulncheck/witness_test.go
deleted file mode 100644
index 348b86d..0000000
--- a/vulncheck/witness_test.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2021 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.
-
-package vulncheck
-
-import (
- "reflect"
- "strings"
- "testing"
-)
-
-// chainsToString converts map Vuln:chains to Vuln.PkgPath:["pkg1->...->pkgN", ...]
-// string representation.
-func chainsToString(chains map[*Vuln][]ImportChain) map[string][]string {
- m := make(map[string][]string)
- for v, chs := range chains {
- var chsStr []string
- for _, ch := range chs {
- var chStr []string
- for _, imp := range ch {
- chStr = append(chStr, imp.Path)
- }
- chsStr = append(chsStr, strings.Join(chStr, "->"))
- }
- m[v.PkgPath] = chsStr
- }
- return m
-}
-
-// stacksToString converts map *Vuln:stacks to Vuln.Symbol:["f1->...->fN", ...]
-// string representation.
-func stacksToString(stacks map[*Vuln][]CallStack) map[string][]string {
- m := make(map[string][]string)
- for v, sts := range stacks {
- var stsStr []string
- for _, st := range sts {
- var stStr []string
- for _, call := range st {
- stStr = append(stStr, call.Function.Name)
- }
- stsStr = append(stsStr, strings.Join(stStr, "->"))
- }
- m[v.Symbol] = stsStr
- }
- return m
-}
-
-func TestImportChains(t *testing.T) {
- // Package import structure for the test program
- // entry1 entry2
- // | |
- // interm1 |
- // | \ |
- // | interm2
- // | / |
- // vuln1 vuln2
- e1 := &PkgNode{ID: 1, Path: "entry1"}
- e2 := &PkgNode{ID: 2, Path: "entry2"}
- i1 := &PkgNode{ID: 3, Path: "interm1", ImportedBy: []int{1}}
- i2 := &PkgNode{ID: 4, Path: "interm2", ImportedBy: []int{2, 3}}
- v1 := &PkgNode{ID: 5, Path: "vuln1", ImportedBy: []int{3, 4}}
- v2 := &PkgNode{ID: 6, Path: "vuln2", ImportedBy: []int{4}}
-
- ig := &ImportGraph{
- Packages: map[int]*PkgNode{1: e1, 2: e2, 3: i1, 4: i2, 5: v1, 6: v2},
- Entries: []int{1, 2},
- }
- vuln1 := &Vuln{ImportSink: 5, PkgPath: "vuln1"}
- vuln2 := &Vuln{ImportSink: 6, PkgPath: "vuln2"}
- res := &Result{Imports: ig, Vulns: []*Vuln{vuln1, vuln2}}
-
- // The chain entry1->interm1->interm2->vuln1 is not reported
- // as there exist a shorter trace going from entry1 to vuln1
- // via interm1.
- want := map[string][]string{
- "vuln1": {"entry1->interm1->vuln1", "entry2->interm2->vuln1"},
- "vuln2": {"entry2->interm2->vuln2", "entry1->interm1->interm2->vuln2"},
- }
-
- chains := ImportChains(res)
- if got := chainsToString(chains); !reflect.DeepEqual(want, got) {
- t.Errorf("want %v; got %v", want, got)
- }
-}
-
-func TestCallStacks(t *testing.T) {
- // Call graph structure for the test program
- // entry1 entry2
- // | |
- // interm1(std) |
- // | \ /
- // | interm2(interface)
- // | / |
- // vuln1 vuln2
- e1 := &FuncNode{ID: 1, Name: "entry1"}
- e2 := &FuncNode{ID: 2, Name: "entry2"}
- i1 := &FuncNode{ID: 3, Name: "interm1", PkgPath: "net/http", CallSites: []*CallSite{&CallSite{Parent: 1, Resolved: true}}}
- i2 := &FuncNode{ID: 4, Name: "interm2", CallSites: []*CallSite{&CallSite{Parent: 2, Resolved: true}, &CallSite{Parent: 3, Resolved: true}}}
- v1 := &FuncNode{ID: 5, Name: "vuln1", CallSites: []*CallSite{&CallSite{Parent: 3, Resolved: true}, &CallSite{Parent: 4, Resolved: false}}}
- v2 := &FuncNode{ID: 6, Name: "vuln2", CallSites: []*CallSite{&CallSite{Parent: 4, Resolved: false}}}
-
- cg := &CallGraph{
- Functions: map[int]*FuncNode{1: e1, 2: e2, 3: i1, 4: i2, 5: v1, 6: v2},
- Entries: []int{1, 2},
- }
- vuln1 := &Vuln{CallSink: 5, Symbol: "vuln1"}
- vuln2 := &Vuln{CallSink: 6, Symbol: "vuln2"}
- res := &Result{Calls: cg, Vulns: []*Vuln{vuln1, vuln2}}
-
- want := map[string][]string{
- "vuln1": {"entry2->interm2->vuln1", "entry1->interm1->vuln1"},
- "vuln2": {"entry2->interm2->vuln2", "entry1->interm1->interm2->vuln2"},
- }
-
- stacks := CallStacks(res)
- if got := stacksToString(stacks); !reflect.DeepEqual(want, got) {
- t.Errorf("want %v; got %v", want, got)
- }
-}
To view, visit change 395256. To unsubscribe, or for help writing mail filters, visit settings.