java-topology/defects/pylons/patch/pylons-0003-toposorter-order-set.patch

50 lines
2 KiB
Diff

# UNDF: UNDF-2026-000000230
Fixes pylons-0003: TopologicalSorter.remove() — `self.order.remove(tuple)` list scan O(E) per edge — CWE-407.
--- a/src/pyramid/util.py
+++ b/src/pyramid/util.py
@@ DEFECT pylons-0003: TopologicalSorter.__init__/add/remove lines 438, 455, 460, 492, 498
class TopologicalSorter:
def __init__(self, ...):
...
- self.order = [] # list — O(E) remove below — CWE-407
+ self.order = set() # FIX pylons-0003: set for O(1) discard
def remove(self, name):
...
for u in after:
- self.order.remove((u, name)) # O(E) list scan — CWE-407
+ self.order.discard((u, name)) # O(1) set discard — fixed
...
for u in before:
- self.order.remove((name, u)) # O(E) list scan — CWE-407
+ self.order.discard((name, u)) # O(1) set discard — fixed
def add(self, name, val, after=None, before=None):
...
if after is not None:
...
- self.order += [(u, name) for u in after] # list extend
+ self.order.update((u, name) for u in after) # set update
if before is not None:
...
- self.order += [(name, o) for o in before] # list extend
+ self.order.update((name, o) for o in before) # set update
def sorted(self):
order = [(self.first, self.last)]
for a, b in self.order: # iteration over set — O(E), correct
order.append((a, b))
...
# SUMMARY:
# self.order changed list → set
# remove(): self.order.remove() O(E) → O(1) via set.discard()
# add(): self.order += O(1) → O(1) via set.update()
# sorted(): for a,b in self.order — O(E) iteration unchanged
#
# Edge uniqueness: duplicate (a,b) pairs have no effect in the sort algorithm
# (add_arc increments in-degree twice for same edge — a pre-existing latent defect).
# The set deduplicates silently, which is correct behavior.