From 95e5e90454d4fd0a013ed3975539602c0d3f707b Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 10 Jun 2014 12:36:40 -0400 Subject: [PATCH] go.tools/oracle: callgraph: fix crash caused by sparse node numbering. Revision 0ea4058a1ca3 caused the node numbering to become sparse, violating a precondition of (*callgraphResult).toSerial. Now we renumber the callgraph nodes always, not just the qpos != nil case. Fixes golang/go#8171 LGTM=crawshaw R=crawshaw CC=golang-codereviews https://golang.org/cl/103240044 --- oracle/callgraph.go | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/oracle/callgraph.go b/oracle/callgraph.go index 1de25cd0..feda3db9 100644 --- a/oracle/callgraph.go +++ b/oracle/callgraph.go @@ -26,52 +26,52 @@ func doCallgraph(o *Oracle, qpos *QueryPos) (queryResult, error) { cg.DeleteSyntheticNodes() var qpkg *types.Package - var roots []*callgraph.Node + var isQueryPkg func(fn *ssa.Function) bool + var keep, remove, roots []*callgraph.Node if qpos == nil { // No -pos provided: show complete callgraph. roots = append(roots, cg.Root) - + isQueryPkg = func(fn *ssa.Function) bool { return true } } else { // A query -pos was provided: restrict result to // functions belonging to the query package. qpkg = qpos.info.Pkg - isQueryPkg := func(fn *ssa.Function) bool { + isQueryPkg = func(fn *ssa.Function) bool { return fn.Pkg != nil && fn.Pkg.Object == qpkg } + } - // First compute the nodes to keep and remove. - var nodes, remove []*callgraph.Node - for fn, cgn := range cg.Nodes { - if isQueryPkg(fn) { - nodes = append(nodes, cgn) - } else { - remove = append(remove, cgn) + // First compute the nodes to keep and remove. + for fn, cgn := range cg.Nodes { + if isQueryPkg(fn) { + keep = append(keep, cgn) + } else { + remove = append(remove, cgn) + } + } + + // Compact the Node.ID sequence of the kept nodes, + // preserving the original order. + sort.Sort(nodesByID(keep)) + for i, cgn := range keep { + cgn.ID = i + } + + // Compute the set of roots: + // in-package nodes with out-of-package callers. + // For determinism, roots are ordered by original Node.ID. + for _, cgn := range keep { + for _, e := range cgn.In { + if !isQueryPkg(e.Caller.Func) { + roots = append(roots, cgn) + break } } + } - // Compact the Node.ID sequence of the remaining - // nodes, preserving the original order. - sort.Sort(nodesByID(nodes)) - for i, cgn := range nodes { - cgn.ID = i - } - - // Compute the set of roots: - // in-package nodes with out-of-package callers. - // For determinism, roots are ordered by original Node.ID. - for _, cgn := range nodes { - for _, e := range cgn.In { - if !isQueryPkg(e.Caller.Func) { - roots = append(roots, cgn) - break - } - } - } - - // Finally, discard all out-of-package nodes. - for _, cgn := range remove { - cg.DeleteNode(cgn) - } + // Finally, discard all out-of-package nodes. + for _, cgn := range remove { + cg.DeleteNode(cgn) } return &callgraphResult{qpkg, cg.Nodes, roots}, nil