java-topology/defects/pyramid/patch/pyramid-0005-registry-introspectable-set.patch

40 lines
1.9 KiB
Diff

# UNDF: UNDF-2026-000000235
Fixes pyramid-0005: registry.py Introspector.relate()/unrelate() — list-backed relationship tracking with O(n) membership and removal.
--- a/src/pyramid/registry.py
+++ b/src/pyramid/registry.py
@@ DEFECT pyramid-0005: Introspector.relate()/unrelate() lines 185-199
class Introspector:
def __init__(self):
self._categories = {}
- self._refs = {} # introspectable → list of related — CWE-407
+ self._refs = {} # introspectable → list of related (preserved for related())
+ self._refs_set = {} # FIX pyramid-0005: introspectable → set for O(1) ops
def relate(self, *pairs):
introspectables = self._get_intrs_by_pairs(pairs)
relatable = ((x, y) for x in introspectables for y in introspectables)
for x, y in relatable:
L = self._refs.setdefault(x, [])
- if x is not y and y not in L: # O(n) list scan — CWE-407
+ S = self._refs_set.setdefault(x, set())
+ if x is not y and y not in S: # O(1) set lookup — fixed
L.append(y)
+ S.add(y)
def unrelate(self, *pairs):
introspectables = self._get_intrs_by_pairs(pairs)
relatable = ((x, y) for x in introspectables for y in introspectables)
for x, y in relatable:
L = self._refs.get(x, [])
- if y in L: # O(n) list scan — CWE-407
- L.remove(y) # O(n) list removal — CWE-407
+ S = self._refs_set.get(x, set())
+ if y in S: # O(1) set lookup — fixed
+ L.remove(y) # O(n) but confirmed; one call per unrelate
+ S.discard(y)
# NOTE: _refs list is kept for related() return value (callers may rely on list type).
# _refs_set shadow provides O(1) dedup in relate() and O(1) guard in unrelate().