callgraph

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2026 License: Apache-2.0 Imports: 0 Imported by: 0

Documentation

Overview

Package callgraph is the deterministic call-graph domain model (Tier-2 shared foundation): a directed graph of function-call edges plus the entrypoints reachability is measured from, and the pure query primitives over it. It is the SEAM both Tier-2 consumers build on – reachability PROOF ("is this vulnerable symbol actually called?") and taint SAST ("does a source reach a sink?").

The model is deterministic and tool-agnostic: a builder adapter (Go SSA / govulncheck-class, shelled via argv) produces a Graph; the queries here are pure Go, so they are table-testable with no tool and a Tier-2 result is reproducible. Node identity is the same "importPath.Symbol" convention the OSV adapter emits for a vulnerability's affected symbols – so a reachability query can intersect call-graph nodes with a vuln's AffectedSymbols directly, with no translation.

SCOPE: this models REACHABILITY (does a call path exist). Taint analysis needs richer edges – which argument/return flows, and sanitizer nodes that break a path – so it layers its OWN edge-attribute + sanitizer model on top of this node-identity convention rather than stretching Edge with optional taint fields (which would degrade the reachability primitive). Edge here stays a plain call edge.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Edge

type Edge struct {
	Caller  string
	Callees []string
}

Edge is one node's outgoing calls: Caller calls each symbol in Callees. Symbols are "importPath.Symbol" identities (e.g. "github.com/foo/bar.Vuln"), matching vulnerability AffectedSymbols.

type Graph

type Graph struct {
	Entrypoints []string
	Edges       []Edge
	// Positions carries no json tag to match Entrypoints/Edges: the domain Graph is never marshaled
	// directly — the synapse-callgraph wire type (taintcallgraph.wireGraph) owns serialization.
	Positions map[string]string
	// BlindConstructs names reachable-surface constructs the builder could NOT follow (reflection, cgo,
	// go:linkname, unsafe function calls). It is analysis-WIDE: any not_reachable verdict derived from this
	// graph is unsound while a blind construct is present, so a reachability consumer must refuse to suppress
	// on it (EPIC #1042 #1065). Empty means the builder saw no such construct. Descriptive only: the
	// adjacency/Reachable/PathTo queries never read it.
	BlindConstructs []string
	// BlindSymbols narrows a bounded opaque edge to the symbols it may reach. Unlike BlindConstructs, an
	// entry here taints only that symbol's result, so an independently disjoint negative remains usable.
	BlindSymbols map[string][]string
}

Graph is a deterministic call graph: the call Edges plus the Entrypoints reachability is measured from (a Go build's main + exported API). A builder adapter populates it; the query methods are pure.

Positions is an OPTIONAL side table: a first-party node's "importPath.Symbol" → its definition position as "relpath:line" (relative to the scan root, never an absolute host path). It exists so a taint SAST finding can cite a file:line for the sink-using function instead of only its symbol (def-use precision; a coarse, function-granular over-approximation — the function's definition line, not the exact sink call site). It is purely descriptive: the reachability queries (adjacency/Reachable/PathTo) never read it, so a builder that omits it (empty map) degrades gracefully to symbol-only locations. Only file PATHS + lines are carried here — never file CONTENTS (GR3).

func (Graph) PathTo

func (g Graph) PathTo(target string) []string

PathTo returns a shortest call path from an entrypoint to target as [entrypoint,..., target] – the PROOF that target is reachable (an explainable "main → … → vulnFunc" chain). It returns nil when target is unreachable from every entrypoint (including when target is not in the graph). A single-element path means target is itself an entrypoint. BFS, so the path is shortest; cycle-safe. When several shortest paths exist, the one via the earliest entrypoint then earliest edge order wins – deterministic for a fixed Graph (golden tests + the human-facing reachability proof depend on this).

func (Graph) Reachable

func (g Graph) Reachable() map[string]bool

Reachable returns the set of symbols reachable from any entrypoint by following call edges forward (the entrypoints themselves are included). Cycle-safe. Build once, then test many candidate symbols against it – the shape it wants when filtering a vuln's AffectedSymbols to the reachable ones.

func (Graph) Reaches

func (g Graph) Reaches(target string) bool

Reaches reports whether target is reachable from any entrypoint.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL