java-topology/defects/networkx/patch/nx-0001-cycles-B-defaultdict-set.patch

45 lines
2.1 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000182
From: agent-blackops <blackops@unturf.com>
Date: Thu, 26 Mar 2026 00:00:00 +0000
Subject: [PATCH] algorithms/cycles: replace B defaultdict(list) with defaultdict(set) in recursive_simple_cycles
CWE-407: Algorithmic complexity via O(N) list membership test in
recursive_simple_cycles(). B was a defaultdict(list) used to track
graph portions yielding no elementary circuit. The inner loop called
`if thisnode not in B[nextnode]` (O(|B[nextnode]|)) followed by
`B[nextnode].append(thisnode)` inside circuit(), which is invoked for
every edge in every DFS frame. Total cost per component is O(E × |B|).
Replace with defaultdict(set): `not in` on a set is O(1) amortised;
`add` replaces `append`. The `_unblock` helper uses `pop()` on the
collection — set.pop() is valid and semantically equivalent here since
order does not matter for unblocking. No algorithmic contract changes.
Defect-Id: NX-001
Severity: MEDIUM
CWE: CWE-407 (Inefficient Algorithmic Complexity)
---
networkx/algorithms/cycles.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/networkx/algorithms/cycles.py b/networkx/algorithms/cycles.py
index xxxxxxx..yyyyyyy 100644
--- a/networkx/algorithms/cycles.py
+++ b/networkx/algorithms/cycles.py
@@ -840,11 +840,11 @@ def recursive_simple_cycles(G):
if closed:
_unblock(thisnode)
else:
for nextnode in component[thisnode]:
- if thisnode not in B[nextnode]: # TODO: use set for speedup?
- B[nextnode].append(thisnode)
+ if thisnode not in B[nextnode]: # CWE-407 fix: O(1) set lookup
+ B[nextnode].add(thisnode) # CWE-407 fix: O(1) set insert
path.pop() # remove thisnode from path
return closed
path = [] # stack of nodes in current path
blocked = defaultdict(bool) # vertex: blocked from search?
- B = defaultdict(list) # graph portions that yield no elementary circuit
+ B = defaultdict(set) # CWE-407 fix: set for O(1) membership and insert
result = [] # list to accumulate the circuits found