From 279f32f97d5fedfe1447b28d5db10a83225af911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Wed, 21 Jan 2026 18:10:49 -0500 Subject: [PATCH] Fix infinite loop when collecting transitive excluded gems The code was modifying the `excluded` array while iterating over it with `.each`. In Ruby, `.each` continues to process newly added elements, which can cause excessive iterations or infinite loops when circular dependencies are present in the gem graph. This caused 100% CPU usage in some environments. Fixes #3912 --- lib/ruby_indexer/lib/ruby_indexer/configuration.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ruby_indexer/lib/ruby_indexer/configuration.rb b/lib/ruby_indexer/lib/ruby_indexer/configuration.rb index 311c821e42..46afacca99 100644 --- a/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +++ b/lib/ruby_indexer/lib/ruby_indexer/configuration.rb @@ -227,7 +227,7 @@ def initial_excluded_gems others.uniq! others.map!(&:name) - excluded.each do |dependency| + transitive_excluded = excluded.each_with_object([]) do |dependency, acc| next unless dependency.runtime? spec = dependency.to_spec @@ -236,7 +236,7 @@ def initial_excluded_gems spec.dependencies.each do |transitive_dependency| next if others.include?(transitive_dependency.name) - excluded << transitive_dependency + acc << transitive_dependency end rescue Gem::MissingSpecError # If a gem is scoped only to some specific platform, then its dependencies may not be installed either, but they @@ -244,6 +244,7 @@ def initial_excluded_gems # just ignore if they're missing end + excluded.concat(transitive_excluded) excluded.uniq! excluded.map(&:name) rescue Bundler::GemfileNotFound