51 lines
2.1 KiB
Diff
51 lines
2.1 KiB
Diff
# UNDF: UNDF-2026-000000265
|
||
From: agent-blackops <blackops@unturf.com>
|
||
Date: Thu, 26 Mar 2026 00:00:00 +0000
|
||
Subject: [PATCH] cop/ignored_node: replace @ignored_nodes Array with identity Set
|
||
|
||
CWE-407: Algorithmic complexity via O(N) linear scan in IgnoredNode.
|
||
@ignored_nodes was initialised as a plain Array. Both `ignored_node?`
|
||
(uses `any? { |n| n.equal?(node) }`) and `part_of_ignored_node?`
|
||
(uses `map(&:loc).any?`) iterate the full array on each call. In
|
||
string-literal cops, `on_str` fires for every string node in a file;
|
||
if R string nodes and S ignored nodes exist the total cost is O(R × S).
|
||
|
||
Fix: initialise @ignored_nodes as `Set.new.compare_by_identity`.
|
||
`compare_by_identity` makes the Set use object identity (same as
|
||
`equal?`) for equality and hash, so `include?(node)` is O(1). The
|
||
`ignore_node` method's `<<` append works unchanged on Set.
|
||
|
||
`part_of_ignored_node?` iterates over ignored node locations rather than
|
||
testing membership — it cannot be collapsed to a bare `include?` — but
|
||
it benefits from the reduced iteration cost when combined with early-exit
|
||
and, more importantly, from not being called for nodes already confirmed
|
||
via `ignored_node?`. The `map(&:loc).any?` pattern is left structurally
|
||
intact; only the backing collection changes.
|
||
|
||
Defect-Id: rubocop-0001
|
||
Severity: MEDIUM
|
||
CWE: CWE-407 (Inefficient Algorithmic Complexity)
|
||
---
|
||
lib/rubocop/cop/ignored_node.rb | 4 ++--
|
||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||
|
||
diff --git a/lib/rubocop/cop/ignored_node.rb b/lib/rubocop/cop/ignored_node.rb
|
||
index xxxxxxx..yyyyyyy 100644
|
||
--- a/lib/rubocop/cop/ignored_node.rb
|
||
+++ b/lib/rubocop/cop/ignored_node.rb
|
||
@@ -24,12 +24,12 @@ module RuboCop
|
||
def ignored_node?(node)
|
||
- # Same object found in array?
|
||
- ignored_nodes.any? { |n| n.equal?(node) }
|
||
+ # O(1) identity-based Set lookup — CWE-407 fix
|
||
+ ignored_nodes.include?(node)
|
||
end
|
||
|
||
private
|
||
|
||
def ignored_nodes
|
||
- @ignored_nodes ||= []
|
||
+ @ignored_nodes ||= Set.new.compare_by_identity # CWE-407 fix: O(1) identity set
|
||
end
|
||
end
|
||
end
|