java-topology/defects/ruby/patch/solargraph-0002-constants-skip-set.patch

55 lines
2.5 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000000266
From: agent-blackops <blackops@unturf.com>
Date: Thu, 26 Mar 2026 00:00:00 +0000
Subject: [PATCH] api_map/constants: remove skip.to_a conversion in inner_get_constants
CWE-407: Algorithmic complexity via unnecessary Array conversion of a
Set inside a recursive method in Constants#inner_get_constants.
`skip` is already a Set throughout the call chain — it is created as
`Set.new` in `collect_and_cache` and passed into `inner_qualify` as
`Set.new` in `qualify_namespace`. However, inside `inner_get_constants`
two lines call `pin.closure.gates - skip.to_a`:
pre_fqns = resolve(pre.name, pin.closure.gates - skip.to_a) # line 262
inc_fqns = resolve(pin.name, pin.closure.gates - skip.to_a) # line 267
`skip.to_a` allocates a new Array on every call. `gates - array`
performs an O(|gates| × |skip|) set-difference by linear scan. Because
`inner_get_constants` is recursive (called for prepends, includes, and
superclass chains), the total cost is O(depth × |gates| × |skip|²) per
`collect` call.
Fix: pass `skip` directly. `Array - Set` is supported in Ruby (Set
responds to `include?` which Array#- uses internally via Enumerable),
so `gates - skip` is O(|gates|) with O(1) per-element lookup. No
`.to_a` allocation needed.
Defect-Id: solargraph-0002
Severity: MEDIUM
CWE: CWE-407 (Inefficient Algorithmic Complexity)
---
lib/solargraph/api_map/constants.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/solargraph/api_map/constants.rb b/lib/solargraph/api_map/constants.rb
index xxxxxxx..yyyyyyy 100644
--- a/lib/solargraph/api_map/constants.rb
+++ b/lib/solargraph/api_map/constants.rb
@@ -258,10 +258,10 @@ module Solargraph
def inner_get_constants fqns, visibility, skip
return [] if fqns.nil? || skip.include?(fqns)
skip.add fqns
result = []
store.get_prepends(fqns).each do |pre|
- pre_fqns = resolve(pre.name, pre.closure.gates - skip.to_a)
+ pre_fqns = resolve(pre.name, pre.closure.gates - skip) # CWE-407 fix: skip is Set, no .to_a
result.concat inner_get_constants(pre_fqns, [:public], skip)
end
result.concat(store.get_constants(fqns, visibility).sort { |a, b| a.name <=> b.name })
store.get_includes(fqns).each do |pin|
- inc_fqns = resolve(pin.name, pin.closure.gates - skip.to_a)
+ inc_fqns = resolve(pin.name, pin.closure.gates - skip) # CWE-407 fix: skip is Set, no .to_a
result.concat inner_get_constants(inc_fqns, [:public], skip)
end