58 lines
2.4 KiB
Diff
58 lines
2.4 KiB
Diff
# UNDF: UNDF-2026-000000234
|
|
Fixes pyramid-0004: util.py TopologicalSorter.sorted() — list used as queue with O(n) pop(0)/insert(0) and O(n) roots membership + remove().
|
|
|
|
--- a/src/pyramid/util.py
|
|
+++ b/src/pyramid/util.py
|
|
|
|
@@ DEFECT pyramid-0004: TopologicalSorter.sorted() lines 503-561
|
|
|
|
+from collections import deque
|
|
|
|
def sorted(self):
|
|
order = [(self.first, self.last)]
|
|
- roots = [] # list — O(n) pop(0)/insert(0)/in/remove — CWE-407
|
|
+ roots = deque() # FIX pyramid-0004: deque for O(1) popleft/appendleft
|
|
+ roots_set = set() # FIX pyramid-0004: O(1) membership test
|
|
graph = {}
|
|
|
|
def add_node(node):
|
|
if node not in graph:
|
|
- roots.append(node)
|
|
+ roots.append(node) # O(1) deque append
|
|
+ roots_set.add(node)
|
|
graph[node] = [0]
|
|
|
|
def add_arc(fromnode, tonode):
|
|
graph[fromnode].append(tonode)
|
|
graph[tonode][0] += 1
|
|
- if tonode in roots: # O(n) list scan — CWE-407
|
|
- roots.remove(tonode) # O(n) list removal — CWE-407
|
|
+ if tonode in roots_set: # O(1) set lookup — fixed
|
|
+ roots.remove(tonode) # O(n) deque remove — still needed; rare case
|
|
+ roots_set.discard(tonode)
|
|
|
|
# ... (node/arc setup unchanged) ...
|
|
|
|
sorted_names = []
|
|
while roots:
|
|
- root = roots.pop(0) # O(n) list pop from front — CWE-407
|
|
+ root = roots.popleft() # O(1) deque popleft — fixed
|
|
+ roots_set.discard(root)
|
|
sorted_names.append(root)
|
|
children = graph[root][1:]
|
|
for child in children:
|
|
arcs = graph[child][0]
|
|
arcs -= 1
|
|
graph[child][0] = arcs
|
|
if arcs == 0:
|
|
- roots.insert(0, child) # O(n) list insert at front — CWE-407
|
|
+ roots.appendleft(child) # O(1) deque appendleft — fixed
|
|
+ roots_set.add(child)
|
|
del graph[root]
|
|
|
|
# SUMMARY: Four O(n) list operations replaced:
|
|
# roots.pop(0) → roots.popleft() O(n) → O(1)
|
|
# roots.insert(0) → roots.appendleft() O(n) → O(1)
|
|
# tonode in roots → tonode in roots_set O(n) → O(1)
|
|
# roots.remove() → roots.remove() O(n) → O(n) [rare; deque.remove still O(n)]
|
|
# Net: O(E²) → O(E log E) or better for most tween/deriver graphs.
|