vulncheck: make API use IDs for entries and proper names for nodes
The change also introduces a small fix to an issue related to entry
points.
Cherry-picked: https://go-review.googlesource.com/c/exp/+/371774
Change-Id: I2d9dc6d0f6a16f1d9546faf362658ad50c9e4f46
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/395050
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/vulncheck/helpers_test.go b/vulncheck/helpers_test.go
index 27ec03b..b275d78 100644
--- a/vulncheck/helpers_test.go
+++ b/vulncheck/helpers_test.go
@@ -114,14 +114,14 @@
}
m := make(map[string][]string)
- for _, n := range cg.Funcs {
+ for _, n := range cg.Functions {
fName := funcName(n)
for _, callsite := range n.CallSites {
e := edge{src: callsite.Parent, dst: n.ID}
if seen[e] {
continue
}
- caller := cg.Funcs[e.src]
+ caller := cg.Functions[e.src]
callerName := funcName(caller)
m[callerName] = append(m[callerName], fName)
}
diff --git a/vulncheck/source.go b/vulncheck/source.go
index 72151d4..c195006 100644
--- a/vulncheck/source.go
+++ b/vulncheck/source.go
@@ -30,7 +30,7 @@
result := &Result{
Imports: &ImportGraph{Packages: make(map[int]*PkgNode)},
Requires: &RequireGraph{Modules: make(map[int]*ModNode)},
- Calls: &CallGraph{Funcs: make(map[int]*FuncNode)},
+ Calls: &CallGraph{Functions: make(map[int]*FuncNode)},
}
vulnPkgModSlice(pkgs, modVulns, result)
@@ -68,7 +68,7 @@
// 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)
+ result.Imports.Entries = append(result.Imports.Entries, e.ID)
}
}
@@ -172,6 +172,17 @@
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 {
@@ -256,7 +267,7 @@
// 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)
+ result.Calls.Entries = append(result.Calls.Entries, e.ID)
}
}
}
@@ -320,7 +331,7 @@
funNode = funcNode(f)
analyzed[f] = funNode
}
- result.Calls.Funcs[funNode.ID] = funNode
+ result.Calls.Functions[funNode.ID] = funNode
// Save node predecessor information.
for _, calleeSliceInfo := range onSlice {
diff --git a/vulncheck/source_test.go b/vulncheck/source_test.go
index 24127e0..ed25385 100644
--- a/vulncheck/source_test.go
+++ b/vulncheck/source_test.go
@@ -132,6 +132,14 @@
}
}
+ // 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
// |
@@ -360,6 +368,11 @@
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 {
diff --git a/vulncheck/vulncheck.go b/vulncheck/vulncheck.go
index 82d3117..8561a6e 100644
--- a/vulncheck/vulncheck.go
+++ b/vulncheck/vulncheck.go
@@ -162,10 +162,10 @@
// CallGraph is technically backwards directed, i.e., from a vulnerable function
// towards the program entry functions (see FuncNode).
type CallGraph struct {
- // Funcs contains all call graph nodes as a map: func node id -> func node.
- Funcs map[int]*FuncNode
- // Entries are a subset of Funcs representing vulncheck entry points.
- Entries []*FuncNode
+ // 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 {
@@ -199,8 +199,8 @@
type RequireGraph struct {
// Modules contains all module nodes as a map: module node id -> module node.
Modules map[int]*ModNode
- // Entries are a subset of Modules representing modules of vulncheck entry points.
- Entries []*ModNode
+ // Entries are IDs of a subset of Modules representing modules of vulncheck entry points.
+ Entries []int
}
type ModNode struct {
@@ -221,8 +221,8 @@
type ImportGraph struct {
// Packages contains all package nodes as a map: package node id -> package node.
Packages map[int]*PkgNode
- // Entries are a subset of Packages representing packages of vulncheck entry points.
- Entries []*PkgNode
+ // Entries are IDs of a subset of Packages representing packages of vulncheck entry points.
+ Entries []int
}
type PkgNode struct {