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)