undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
This commit is contained in:
parent
0a580b313d
commit
db29a08762
1311 changed files with 371202 additions and 1188 deletions
83
defects/terraform/patch/tf-0001-dag-tarjan-onstack-map.patch
Normal file
83
defects/terraform/patch/tf-0001-dag-tarjan-onstack-map.patch
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
From: agent-blackops <blackops@unturf.com>
|
||||
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
|
||||
-}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
From: agent-blackops <blackops@unturf.com>
|
||||
Date: Thu, 26 Mar 2026 00:00:00 +0000
|
||||
Subject: [PATCH] dag/graph: rewrite EdgesTo to use upEdgesNoCopy index
|
||||
|
||||
CWE-407: Algorithmic complexity via O(E) full-edge scan in EdgesTo().
|
||||
EdgesTo() iterates g.Edges() (all edges) and filters by target hashcode —
|
||||
O(E) per call. transform_destroy_cbd.go calls EdgesTo inside a
|
||||
for-range over g.Vertices(), producing O(V×E) total comparisons.
|
||||
|
||||
The graph already maintains g.upEdges[hashcode(v)] — a Set of source
|
||||
vertices for every target v, updated incrementally by Connect() and
|
||||
RemoveEdge(). Rewrite EdgesTo to iterate upEdgesNoCopy(v) instead:
|
||||
one hash lookup to get the source set, then one BasicEdge construction
|
||||
per source. Cost is O(in-degree(v)) per call — O(sum of in-degrees) =
|
||||
O(E) total across all vertices, vs O(V×E) before.
|
||||
|
||||
The returned []Edge slice has identical semantics; callers are unaffected.
|
||||
|
||||
Defect-Id: TF-002
|
||||
Severity: MEDIUM
|
||||
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
||||
---
|
||||
internal/dag/graph.go | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/internal/dag/graph.go b/internal/dag/graph.go
|
||||
index xxxxxxx..yyyyyyy 100644
|
||||
--- a/internal/dag/graph.go
|
||||
+++ b/internal/dag/graph.go
|
||||
@@ -79,13 +79,9 @@ func (g *Graph) EdgesFrom(v Vertex) []Edge {
|
||||
// EdgesTo returns the list of edges to the given target.
|
||||
func (g *Graph) EdgesTo(v Vertex) []Edge {
|
||||
- var result []Edge
|
||||
- search := hashcode(v)
|
||||
- for _, e := range g.Edges() {
|
||||
- if hashcode(e.Target()) == search {
|
||||
- result = append(result, e)
|
||||
- }
|
||||
+ // CWE-407 fix: use upEdgesNoCopy index instead of scanning all edges O(E).
|
||||
+ // upEdges[hashcode(v)] holds exactly the set of sources pointing at v;
|
||||
+ // one map lookup + O(in-degree(v)) edge constructions replaces O(E) scan.
|
||||
+ sources := g.upEdgesNoCopy(v)
|
||||
+ result := make([]Edge, 0, sources.Len())
|
||||
+ for _, src := range sources {
|
||||
+ result = append(result, BasicEdge(src.(Vertex), v)) // CWE-407 fix: O(in-degree)
|
||||
}
|
||||
return result
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue