Skip to content

Commit

Permalink
vulncheck: build callgraph in parallel with fetching db
Browse files Browse the repository at this point in the history
Source(...) now builds the *ssa.Program and callgraph from
the *ssa.Program in parallel with fetching vulnerabilities.
Returns as soon as the vuln set is empty.

Updates golang/go#57357

Change-Id: I310b93f7125b5edcc2a5744db9f9f595c70aa5d4
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/460420
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Alan Donovan <[email protected]>
Run-TryBot: Tim King <[email protected]>
Reviewed-by: Zvonimir Pavlinovic <[email protected]>
  • Loading branch information
timothy-king committed Jan 9, 2023
1 parent ff35524 commit 975d4c7
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
34 changes: 29 additions & 5 deletions vulncheck/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"go/token"
"sort"
"sync"

"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/ssa"
Expand Down Expand Up @@ -54,6 +55,28 @@ func Source(ctx context.Context, pkgs []*Package, cfg *Config) (_ *Result, err e
stdlibModule.Version = semver.GoTagToSemver(internal.GoEnv("GOVERSION"))
}

ctx, cancel := context.WithCancel(ctx)
defer cancel()

// If we are building the callgraph, build ssa and the callgraph in parallel
// with fetching vulnerabilities. If the vulns set is empty, return without
// waiting for SSA construction or callgraph to finish.
var (
wg sync.WaitGroup // guards entries, cg, and buildErr
entries []*ssa.Function
cg *callgraph.Graph
buildErr error
)
if !cfg.ImportsOnly {
wg.Add(1)
go func() {
defer wg.Done()
prog, ssaPkgs := buildSSA(pkgs, fset)
entries = entryPoints(ssaPkgs)
cg, buildErr = callGraph(ctx, prog, entries)
}()
}

mods := extractModules(pkgs)
modVulns, err := fetchVulnerabilities(ctx, cfg.Client, mods)
if err != nil {
Expand All @@ -69,15 +92,16 @@ func Source(ctx context.Context, pkgs []*Package, cfg *Config) (_ *Result, err e
vulnPkgModSlice(pkgs, modVulns, result)
setModules(result, mods)
// Return result immediately if in ImportsOnly mode or
// if there are no vulnerable packages, as there is no
// need to build the call graph.
// if there are no vulnerable packages.
if cfg.ImportsOnly || len(result.Imports.Packages) == 0 {
return result, nil
}

prog, ssaPkgs := buildSSA(pkgs, fset)
entries := entryPoints(ssaPkgs)
cg := callGraph(prog, entries)
wg.Wait() // wait for build to finish
if buildErr != nil {
return nil, err
}

vulnCallGraphSlice(entries, modVulns, cg, result)

// Release residual memory.
Expand Down
16 changes: 14 additions & 2 deletions vulncheck/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package vulncheck

import (
"bytes"
"context"
"go/token"
"go/types"
"strings"
Expand Down Expand Up @@ -57,27 +58,38 @@ func buildSSA(pkgs []*Package, fset *token.FileSet) (*ssa.Program, []*ssa.Packag
}

// callGraph builds a call graph of prog based on VTA analysis.
func callGraph(prog *ssa.Program, entries []*ssa.Function) *callgraph.Graph {
func callGraph(ctx context.Context, prog *ssa.Program, entries []*ssa.Function) (*callgraph.Graph, error) {
entrySlice := make(map[*ssa.Function]bool)
for _, e := range entries {
entrySlice[e] = true
}

if err := ctx.Err(); err != nil { // cancelled?
return nil, err
}
initial := cha.CallGraph(prog)
allFuncs := ssautil.AllFunctions(prog)

fslice := forwardReachableFrom(entrySlice, initial)
// Keep only actually linked functions.
pruneSet(fslice, allFuncs)

if err := ctx.Err(); err != nil { // cancelled?
return nil, err
}
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)

if err := ctx.Err(); err != nil { // cancelled?
return nil, err
}
cg := vta.CallGraph(fslice, vtaCg)
cg.DeleteSyntheticNodes()
return cg
return cg, nil
}

// siteCallees computes a set of callees for call site `call` given program `callgraph`.
Expand Down

0 comments on commit 975d4c7

Please sign in to comment.