[vuln] cmd/govulncheck: add progress output

1 view
Skip to first unread message

Zvonimir Pavlinovic (Gerrit)

unread,
Jan 25, 2023, 2:27:46 PM1/25/23
to goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Gopher Robot, Jonathan Amsterdam, golang-co...@googlegroups.com

Zvonimir Pavlinovic submitted this change.

View Change



8 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:

```
The name of the file: cmd/govulncheck/print.go
Insertions: 1, Deletions: 1.

@@ -306,7 +306,7 @@

// sourceProgressMessage returns a string of the form
//
-// "Scanning your code and P packages across M modules for known vulnerabilities..."
+// "Scanning your code and P packages across M dependent modules for known vulnerabilities..."
//
// P is the number of strictly dependent packages of
// topPkgs and Y is the number of their modules.
```

Approvals: Jonathan Amsterdam: Looks good to me, approved Zvonimir Pavlinovic: Run TryBots Gopher Robot: TryBots succeeded
cmd/govulncheck: add progress output

There are two progress output messages: one for source and one for binaries.
The latter one is simpler since the binary analysis is almost instantaneous.

Fixes golang/go#56501
Updates golang/go#56207

Change-Id: I381c8ef3b7db9c87c52ef6b2132b79be940b8b3d
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/463099
TryBot-Result: Gopher Robot <go...@golang.org>
Run-TryBot: Zvonimir Pavlinovic <zpavl...@google.com>
Reviewed-by: Jonathan Amsterdam <j...@google.com>
---
M cmd/govulncheck/main.go
M cmd/govulncheck/main_command_118_test.go
M cmd/govulncheck/print.go
M cmd/govulncheck/testdata/binary.ct
M cmd/govulncheck/testdata/nogomod.ct
M cmd/govulncheck/testdata/source.ct
6 files changed, 111 insertions(+), 13 deletions(-)

diff --git a/cmd/govulncheck/main.go b/cmd/govulncheck/main.go
index d14ee1a..6a8334c 100644
--- a/cmd/govulncheck/main.go
+++ b/cmd/govulncheck/main.go
@@ -37,10 +37,6 @@
const (
envGOVULNDB = "GOVULNDB"
vulndbHost = "https://vuln.go.dev"
-
- introMessage = `govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.
-
-Scanning for dependencies with known vulnerabilities...`
)

func main() {
@@ -51,9 +47,7 @@

`)
flag.PrintDefaults()
- fmt.Fprintf(os.Stderr, `
-For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.
-`)
+ fmt.Fprintf(os.Stderr, "\n%s\n", detailsMessage)
}
flag.Parse()

@@ -121,6 +115,9 @@
}
return err
}
+
+ fmt.Println()
+ fmt.Println(sourceProgressMessage(pkgs))
res, err = govulncheck.Source(ctx, cfg, pkgs)
} else {
var f *os.File
@@ -129,6 +126,9 @@
return err
}
defer f.Close()
+
+ fmt.Println()
+ fmt.Println(binaryProgressMessage)
res, err = gvc.Binary(ctx, cfg, f)
}
if err != nil {
diff --git a/cmd/govulncheck/main_command_118_test.go b/cmd/govulncheck/main_command_118_test.go
index 122e17d..350b83c 100644
--- a/cmd/govulncheck/main_command_118_test.go
+++ b/cmd/govulncheck/main_command_118_test.go
@@ -63,6 +63,7 @@
cmd.Env = append(os.Environ(), "GOVULNDB="+govulndbURI.String())
out, err := cmd.CombinedOutput()
out = filterGoFilePaths(out)
+ out = filterProgressNumbers(out)
out = filterHeapGo(out)
return out, err
}
@@ -95,8 +96,9 @@
}

var (
- goFileRegexp = regexp.MustCompile(`[^\s"]*\.go[\s":]`)
- heapGoRegexp = regexp.MustCompile(`heap\.go:(\d+)`)
+ goFileRegexp = regexp.MustCompile(`[^\s"]*\.go[\s":]`)
+ heapGoRegexp = regexp.MustCompile(`heap\.go:(\d+)`)
+ progressRegexp = regexp.MustCompile(`Scanning your code and (\d+) packages across (\d+)`)
)

// filterGoFilePaths modifies paths to Go files by replacing their directory with "...".
@@ -115,3 +117,7 @@
func filterHeapGo(data []byte) []byte {
return heapGoRegexp.ReplaceAll(data, []byte(`N`))
}
+
+func filterProgressNumbers(data []byte) []byte {
+ return progressRegexp.ReplaceAll(data, []byte("Scanning your code and P packages across M"))
+}
diff --git a/cmd/govulncheck/print.go b/cmd/govulncheck/print.go
index 8b8beac..7bea841 100644
--- a/cmd/govulncheck/print.go
+++ b/cmd/govulncheck/print.go
@@ -16,6 +16,7 @@
"golang.org/x/vuln/exp/govulncheck"
"golang.org/x/vuln/internal"
"golang.org/x/vuln/osv"
+ "golang.org/x/vuln/vulncheck"
)

func printJSON(r *govulncheck.Result) error {
@@ -31,6 +32,12 @@
const (
labelWidth = 16
lineLength = 55
+
+ introMessage = `govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.`
+
+ detailsMessage = `For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.`
+
+ binaryProgressMessage = `Scanning your binary for known vulnerabilities...`
)

func printText(r *govulncheck.Result, verbose, source bool) error {
@@ -296,3 +303,71 @@
}
return string(result)
}
+
+// sourceProgressMessage returns a string of the form
+//
+// "Scanning your code and P packages across M dependent modules for known vulnerabilities..."
+//
+// P is the number of strictly dependent packages of
+// topPkgs and Y is the number of their modules.
+func sourceProgressMessage(topPkgs []*vulncheck.Package) string {
+ pkgs, mods := depPkgsAndMods(topPkgs)
+
+ pkgsPhrase := fmt.Sprintf("%d package", pkgs)
+ if pkgs != 1 {
+ pkgsPhrase += "s"
+ }
+
+ modsPhrase := fmt.Sprintf("%d dependent module", mods)
+ if mods != 1 {
+ modsPhrase += "s"
+ }
+
+ return fmt.Sprintf("Scanning your code and %s across %s for known vulnerabilities...", pkgsPhrase, modsPhrase)
+}
+
+// depPkgsAndMods returns the number of packages that
+// topPkgs depend on and the number of their modules.
+func depPkgsAndMods(topPkgs []*vulncheck.Package) (int, int) {
+ tops := make(map[string]bool)
+ depPkgs := make(map[string]bool)
+ depMods := make(map[string]bool)
+
+ for _, t := range topPkgs {
+ tops[t.PkgPath] = true
+ }
+
+ var visit func(*vulncheck.Package, bool)
+ visit = func(p *vulncheck.Package, top bool) {
+ path := p.PkgPath
+ if depPkgs[path] {
+ return
+ }
+ if tops[path] && !top {
+ // A top package that is a dependency
+ // will not be in depPkgs, so we skip
+ // reiterating on it here.
+ return
+ }
+
+ // We don't count a top-level package as
+ // a dependency even when they are used
+ // as a dependent package.
+ if !tops[path] {
+ depPkgs[path] = true
+ if p.Module != nil { // no module for stdlib
+ depMods[p.Module.Path] = true
+ }
+ }
+
+ for _, d := range p.Imports {
+ visit(d, false)
+ }
+ }
+
+ for _, t := range topPkgs {
+ visit(t, true)
+ }
+
+ return len(depPkgs), len(depMods)
+}
diff --git a/cmd/govulncheck/testdata/binary.ct b/cmd/govulncheck/testdata/binary.ct
index 27a593f..c5237e3 100644
--- a/cmd/govulncheck/testdata/binary.ct
+++ b/cmd/govulncheck/testdata/binary.ct
@@ -1,7 +1,7 @@
$ govulncheck ${vuln_binary} --> FAIL 3
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.

-Scanning for dependencies with known vulnerabilities...
+Scanning your binary for known vulnerabilities...
Your code is affected by 1 vulnerability from 1 module.

Vulnerability #1: GO-2021-0113
diff --git a/cmd/govulncheck/testdata/nogomod.ct b/cmd/govulncheck/testdata/nogomod.ct
index 8f4a255..75bf07d 100644
--- a/cmd/govulncheck/testdata/nogomod.ct
+++ b/cmd/govulncheck/testdata/nogomod.ct
@@ -2,8 +2,6 @@

$ govulncheck -dir ${moddir}/nogomod . --> FAIL 1
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.
-
-Scanning for dependencies with known vulnerabilities...
govulncheck: no go.mod file

govulncheck only works Go with modules. Try navigating to your module directory.
diff --git a/cmd/govulncheck/testdata/source.ct b/cmd/govulncheck/testdata/source.ct
index 51559fa..1f2c042 100644
--- a/cmd/govulncheck/testdata/source.ct
+++ b/cmd/govulncheck/testdata/source.ct
@@ -1,7 +1,7 @@
$ govulncheck -dir ${moddir}/vuln -v . --> FAIL 3
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.

-Scanning for dependencies with known vulnerabilities...
+Scanning your code and P packages across M dependent modules for known vulnerabilities...
Your code is affected by 1 vulnerability from 1 module.

Vulnerability #1: GO-2021-0113

To view, visit change 463099. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: vuln
Gerrit-Branch: master
Gerrit-Change-Id: I381c8ef3b7db9c87c52ef6b2132b79be940b8b3d
Gerrit-Change-Number: 463099
Gerrit-PatchSet: 10
Gerrit-Owner: Zvonimir Pavlinovic <zpavl...@google.com>
Gerrit-Reviewer: Gopher Robot <go...@golang.org>
Gerrit-Reviewer: Jonathan Amsterdam <j...@google.com>
Gerrit-Reviewer: Zvonimir Pavlinovic <zpavl...@google.com>
Gerrit-MessageType: merged
Reply all
Reply to author
Forward
0 new messages