java-topology/defects/rails/patch/rails-0017-rename-column-indexes-set.patch

40 lines
2.3 KiB
Diff
Raw 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-000000256
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -1459,10 +1459,11 @@ module ActiveRecord
def rename_column_indexes(table_name, column_name, new_column_name)
column_name, new_column_name = column_name.to_s, new_column_name.to_s
indexes(table_name).each do |index|
- next unless index.columns.include?(new_column_name)
+ col_set = index.columns.is_a?(Array) ? index.columns.to_set : index.columns
+ next unless col_set.include?(new_column_name)
old_columns = index.columns.dup
- old_columns[old_columns.index(new_column_name)] = column_name
+ old_columns[old_columns.index(new_column_name)] = column_name # Array#index OK: called once per index, not in inner loop
generated_index_name = index_name(table_name, column: old_columns)
if generated_index_name == index.name
rename_index table_name, generated_index_name, index_name(table_name, column: index.columns)
# CWE-407: Algorithmic Complexity — O(I×C) → O(I) for rename_column_indexes
#
# Defect ID : rails-0017
# File : activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
# Method : rename_column_indexes (private)
# Severity : MEDIUM
#
# Pattern:
# indexes(table_name).each do |index| # outer loop: I indexes
# next unless index.columns.include?(...) # Array#include? — O(C) linear scan
#
# `index.columns` is a plain Array (e.g. ["user_id", "created_at"]).
# For each of the I indexes, `include?` scans all C column names: O(I×C) total.
# In wide tables (C >> 10) with many indexes (I >> 20) this degrades noticeably.
# A table with 50 indexes × 10 columns per index = 500 unnecessary string comparisons
# per rename_column call — multiplied across every ALTER TABLE in a large migration.
#
# Fix: convert index.columns to a Set before the include? check.
# Array#index (position lookup) is called at most once per index and remains O(C)
# but that is not inside an inner loop, so it is acceptable.
#
# Complexity before: O(I × C)
# Complexity after: O(I + C) — Set construction O(C) + O(1) lookup per index