vulncheck: fix buildSSA's FileSet handling The FileSet used when building a new ssa program should be the same FileSet used when building the Package input because later Position computation is done using the SSA program's FileSet. Moreover, enforce this from the Source API level. If Packages passed to Source were built with different FileSets, that is an error. Cherry-picked: https://go-review.googlesource.com/c/exp/+/392374 Change-Id: Icfed7e76520264d7487dcc8accf1a0b71f7fb74f Reviewed-on: https://go-review.googlesource.com/c/vuln/+/395062 Trust: Julie Qiu <julie@golang.org> Run-TryBot: Julie Qiu <julie@golang.org> Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/vulncheck/source.go b/vulncheck/source.go index b5206e9..8b30bce 100644 --- a/vulncheck/source.go +++ b/vulncheck/source.go
@@ -6,6 +6,8 @@ import ( "context" + "fmt" + "go/token" "runtime" "golang.org/x/tools/go/callgraph" @@ -21,6 +23,23 @@ // - call graph leading to the use of a known vulnerable function // or method func Source(ctx context.Context, pkgs []*Package, cfg *Config) (*Result, error) { + + // 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 @@ -38,7 +57,7 @@ return result, nil } - prog, ssaPkgs := buildSSA(pkgs) + prog, ssaPkgs := buildSSA(pkgs, fset) entries := entryPoints(ssaPkgs) cg := callGraph(prog, entries) vulnCallGraphSlice(entries, modVulns, cg, result)
diff --git a/vulncheck/utils.go b/vulncheck/utils.go index 08448da..780cd63 100644 --- a/vulncheck/utils.go +++ b/vulncheck/utils.go
@@ -23,8 +23,8 @@ // 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) (*ssa.Program, []*ssa.Package) { - prog := ssa.NewProgram(token.NewFileSet(), ssa.BuilderMode(0)) +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)