vagrant-0001: bundler.rb plugin loader runs Array#include? against plugins.keys / system_plugins inside per-spec loops. O(S*P) per vagrant command. Fix: hoist Set.new outside the loop, O(1) per spec lookup. Bench: 127x at S=2000 P=1000. wave5-cicd-iac-survey.md: documents 32 projects scanned across deployment (Spinnaker, fluxcd, Argo Rollouts/Events), modern CI/CD (Earthly, Dagger, Buck2), container runtime (containerd, crun, skopeo, ko, kaniko, buildah), local k8s (kind, minikube, k3s), IaC + testing (Packer, Vagrant, ansible-lint, Molecule, InSpec, Terratest), contract/mutation testing (Pact, Stryker, mutmut, PIT), security (Semgrep, Bandit, gosec), Java quality (Spotbugs, Checkstyle, chart-testing). Clean-scan honor roll +4: chart-testing, kind, ko, pact-ruby.
51 lines
2.3 KiB
Diff
51 lines
2.3 KiB
Diff
# UNDF: UNDF-2026-000001297
|
|
# UNDF: UNDF-2026-XXXXXXXXX
|
|
# CWE-407: Algorithmic Complexity -- O(S*P) -> O(S+P) in Vagrant Bundler plugin paths
|
|
#
|
|
# Defect: Two per-spec loops in lib/vagrant/bundler.rb call .include? on a
|
|
# plain Ruby Array (plugins.keys / system_plugins), giving O(P) per spec.
|
|
# Across S resolved specs, total O(S*P) per vagrant command run. Fires on
|
|
# every vagrant invocation that touches the plugin path.
|
|
#
|
|
# Fix: Hoist a Set built from the array once before each loop. Set#include?
|
|
# is O(1). require "set" already loaded at top of file.
|
|
#
|
|
# Complexity gate (tests/test-vagrant-cwe407.py):
|
|
# S=P=500: fixed must complete in <5ms
|
|
# k-scaling 5x: time ratio must be <17.5x
|
|
--- a/lib/vagrant/bundler.rb
|
|
+++ b/lib/vagrant/bundler.rb
|
|
@@ -466,9 +466,11 @@ module Vagrant
|
|
).uninstall_gem(spec)
|
|
end
|
|
|
|
- solution.find_all do |spec|
|
|
- plugins.keys.include?(spec.name)
|
|
- end
|
|
+ # Hoist plugin name lookup into a Set; previously plugins.keys.include?
|
|
+ # was O(P) per spec, giving O(S*P) on every plugin-pruning call.
|
|
+ plugin_name_set = Set.new(plugins.keys)
|
|
+ solution.find_all { |spec| plugin_name_set.include?(spec.name) }
|
|
end
|
|
|
|
# During the duration of the yielded block, Bundler loud output
|
|
@@ -522,6 +524,8 @@ module Vagrant
|
|
|
|
if Vagrant.strict_dependency_enforcement
|
|
@logger.debug("Enabling strict dependency enforcement")
|
|
+ # Build a Set once for O(1) per-spec membership check.
|
|
+ system_plugin_set = Set.new(system_plugins)
|
|
plugin_deps += vagrant_internal_specs.map do |spec|
|
|
# NOTE: When working within bundler, skip any system plugins and
|
|
# default gems. However, when not within bundler (in the installer)
|
|
@@ -530,7 +534,7 @@ module Vagrant
|
|
# set does allow for resolving conservatively but it can't be set
|
|
# from the public API (requires an instance variable set on the resolver
|
|
# instance) so strict dependencies are used instead.
|
|
- if Vagrant.in_bundler?
|
|
- next if system_plugins.include?(spec.name)
|
|
+ if Vagrant.in_bundler?
|
|
+ next if system_plugin_set.include?(spec.name)
|
|
# # If this spec is for a default plugin included in
|
|
# # the ruby stdlib, ignore it
|
|
next if spec.default_gem?
|