31 lines
1.5 KiB
Diff
31 lines
1.5 KiB
Diff
# UNDF: UNDF-2026-000000233
|
|
Fixes pyramid-0003: config/actions.py resolveConflicts() — list.remove() inside sorted output loop.
|
|
|
|
--- a/src/pyramid/config/actions.py
|
|
+++ b/src/pyramid/config/actions.py
|
|
|
|
@@ DEFECT pyramid-0003: resolveConflicts() line 490
|
|
|
|
# In class _ConflictState.__init__():
|
|
- self.remaining_actions = [] # list — O(n) remove — CWE-407
|
|
+ self.remaining_actions = [] # kept as list for extend/iteration
|
|
+ self.remaining_actions_set = set() # FIX pyramid-0003: O(1) removal
|
|
|
|
# In normalize_actions / state initialization:
|
|
state.remaining_actions.extend(normalize_actions(actions))
|
|
+ state.remaining_actions_set.update(id(a) for a in state.remaining_actions)
|
|
|
|
# In resolveConflicts() yield loop:
|
|
for i, action in sorted(output, key=operator.itemgetter(0)):
|
|
state.min_order = action['order']
|
|
state.start = i + 1
|
|
- state.remaining_actions.remove(action) # O(n) linear scan — CWE-407
|
|
+ state.remaining_actions_set.discard(id(action)) # O(1) — fixed
|
|
+ # remaining_actions list lazily filtered when iterated (or rebuild on demand)
|
|
state.resolved_ainfos[action['discriminator']] = (i, action)
|
|
yield action
|
|
|
|
# NOTE: actions are dicts (unhashable), so we track by id(). The list is
|
|
# kept for ordered iteration in subsequent passes; rebuild by filtering with
|
|
# the set when needed: [a for a in state.remaining_actions if id(a) in set].
|
|
# This converts the O(N²) startup cost to O(N).
|