java-topology/defects/puppet/patch/puppet-0001-paths-in-cycle-set.patch
russell@unturf.com 2e70c9ba26 feat: add RE2 patch UNDF IDs (1270-1273), fix puppet-0001 UNDF ref
salt-0005: UNDF-2026-000001270 (RE2 correct fix)
ansible-0005: UNDF-2026-000001271 (RE2 correct fix)
capistrano-0002: UNDF-2026-000001272 (RE2 correct fix)
puppet-0002: UNDF-2026-000001273 (RE2 correct fix)
puppet-0001 patch header: corrected UNDF ref from placeholder 226 to 1269
Total: 1272 entries
2026-04-13 12:00:31 -04:00

71 lines
2.9 KiB
Diff

# UNDF: UNDF-2026-000001269
From: agent-blackops <blackops@unturf.com>
Date: Thu, 26 Mar 2026 00:00:00 +0000
Subject: [PATCH] graph/simple_graph: replace Array path with Set+Array pair in paths_in_cycle BFS
CWE-407: Algorithmic complexity via O(|cycle|^3) Array#member? in the
BFS loop of paths_in_cycle(). frame[1] is a growing Array used as both
the path record and the membership oracle. Each call to
frame[1].member?(frame[0]) is O(path_length); paths grow as BFS
expands; in the worst case (a fully connected cycle of length N) this
produces O(N^3) total comparisons.
Fix: replace the bare Array path with a two-field frame [vertex,
path_array, path_set] where path_set is a Ruby Set parallel to
path_array. Membership testing uses path_set.include?() for O(1)
average cost. path_array is retained unchanged so that found paths
preserve their ordering and the existing `found.sort` contract is
unchanged.
Ruby's Set (from 'set') gives O(1) average include? via hash-based
storage. No behaviour change; only the membership-test complexity is
affected.
Defect-Id: PUP-001
Severity: LOW (error path — cycles are uncommon in valid Puppet catalogs)
CWE: CWE-407 (Inefficient Algorithmic Complexity)
---
lib/puppet/graph/simple_graph.rb | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/lib/puppet/graph/simple_graph.rb b/lib/puppet/graph/simple_graph.rb
index xxxxxxx..yyyyyyy 100644
--- a/lib/puppet/graph/simple_graph.rb
+++ b/lib/puppet/graph/simple_graph.rb
@@ -1,3 +1,4 @@
+require 'set' # CWE-407 fix
@@ -199,17 +200,17 @@ class Puppet::Graph::SimpleGraph
def paths_in_cycle(cycle, max_paths = 1)
# TRANSLATORS "negative or zero" refers to the count of paths
raise ArgumentError, _("negative or zero max_paths") if max_paths < 1
# Calculate our filtered outbound vertex lists...
adj = {}
cycle.each do |vertex|
adj[vertex] = adjacent(vertex).select { |s| cycle.member? s }
end
found = []
- # frame struct is vertex, [path]
- stack = [[cycle.first, []]]
+ # frame struct is vertex, [path_array], path_set # CWE-407 fix
+ stack = [[cycle.first, [], Set.new]] # CWE-407 fix
while frame = stack.shift # rubocop:disable Lint/AssignmentInCondition
- if frame[1].member?(frame[0]) then
+ if frame[2].include?(frame[0]) then # CWE-407 fix: O(1) vs O(path)
found << frame[1] + [frame[0]]
break if found.length >= max_paths
else
adj[frame[0]].each do |to|
- stack.push [to, frame[1] + [frame[0]]]
+ new_path = frame[1] + [frame[0]]
+ new_set = frame[2] | Set[frame[0]] # CWE-407 fix: O(1) insert
+ stack.push [to, new_path, new_set] # CWE-407 fix
end
end
end
found.sort
end