# UNDF: UNDF-2026-000000307 From: agent-blackops Date: Thu, 26 Mar 2026 00:00:00 +0000 Subject: [PATCH] dag/tarjan: replace inStack linear scan with onStack map CWE-407: Algorithmic complexity via O(V) linear stack scan per call to inStack() inside stronglyConnected(). inStack() iterated s.Stack []Vertex looking for needle — O(stack-depth) per call. stronglyConnected() calls inStack once per outgoing edge, yielding O(V×E) total comparisons for a dense graph. Add onStack map[Vertex]bool to sccAcct. Set onStack[v] = true on push, delete(onStack, v) on pop. Replace inStack(s.Stack, w) with s.onStack[w] for O(1) amortised map lookup per call. The standalone inStack() helper function is removed; the check is now expressed directly as s.onStack[target] in the one call site. Defect-Id: TF-001 Severity: HIGH CWE: CWE-407 (Inefficient Algorithmic Complexity) --- internal/dag/tarjan.go | 22 ++++++++-------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/internal/dag/tarjan.go b/internal/dag/tarjan.go index xxxxxxx..yyyyyyy 100644 --- a/internal/dag/tarjan.go +++ b/internal/dag/tarjan.go @@ -10,6 +10,7 @@ func StronglyConnected(g *Graph) [][]Vertex { acct := sccAcct{ NextIndex: 1, VertexIndex: make(map[Vertex]int, len(vs)), + onStack: make(map[Vertex]bool, len(vs)), // CWE-407 fix: O(1) stack membership } for _, v := range vs { // Recurse on any non-visited nodes @@ -30,7 +31,7 @@ func stronglyConnected(acct *sccAcct, g *Graph, v Vertex) int { if targetIdx == 0 { minIdx = min(minIdx, stronglyConnected(acct, g, target)) - } else if acct.inStack(target) { + } else if acct.onStack[target] { // CWE-407 fix: O(1) map lookup replaces O(V) scan // Check if the vertex is in the stack minIdx = min(minIdx, targetIdx) } @@ -56,6 +57,7 @@ type sccAcct struct { NextIndex int VertexIndex map[Vertex]int Stack []Vertex + onStack map[Vertex]bool // CWE-407 fix: shadow set for O(1) inStack queries SCC [][]Vertex } @@ -64,7 +66,8 @@ func (s *sccAcct) visit(v Vertex) int { idx := s.NextIndex s.VertexIndex[v] = idx s.NextIndex++ - s.push(v) + s.push(v) // push also sets onStack[v] = true return idx } @@ -72,6 +75,7 @@ func (s *sccAcct) push(n Vertex) { s.Stack = append(s.Stack, n) + s.onStack[n] = true // CWE-407 fix: O(1) insert } // pop removes a vertex from the stack @@ -82,20 +86,12 @@ func (s *sccAcct) pop() Vertex { vertex := s.Stack[n-1] s.Stack = s.Stack[:n-1] + delete(s.onStack, vertex) // CWE-407 fix: O(1) remove return vertex } - -// inStack checks if a vertex is in the stack -func (s *sccAcct) inStack(needle Vertex) bool { - for _, n := range s.Stack { - if n == needle { - return true - } - } - return false -}