java-topology/defects/mysql/patch/mysql-0004-dict-index-col-added-hash.patch

62 lines
2.5 KiB
Diff

# UNDF: UNDF-2026-000000178
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -2741,8 +2741,17 @@ static bool dict_index_find_and_set_cols(const dict_table_t *table,
dict_index_t *index,
const dict_add_v_col_t *add_v) {
- std::vector<ulint, ut::allocator<ulint>> col_added;
- std::vector<ulint, ut::allocator<ulint>> v_col_added;
+ /*
+ * CWE-407 fix (mysql-0004): replace O(N) linear-scan vectors with O(1) hash
+ * sets so duplicate-column detection during index field resolution costs O(F)
+ * total rather than O(F²) for an F-field index.
+ *
+ * The old code used std::find on a std::vector<ulint> that grows with each
+ * matched field, producing a triangular-number cost: 0+1+...+(F-1) = F²/2.
+ * Replacing with std::unordered_set<ulint> makes each check O(1).
+ */
+ std::unordered_set<ulint> col_added;
+ std::unordered_set<ulint> v_col_added;
ut_ad(table != nullptr && index != nullptr);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
@@ -2755,13 +2764,11 @@ static bool dict_index_find_and_set_cols(...) {
if (!strcmp(table->get_col_name(j), field->name)) {
/* Check if same column is being assigned again
which suggest that column has duplicate name. */
- bool exists =
- std::find(col_added.begin(), col_added.end(), j) != col_added.end();
+ bool exists = col_added.count(j) > 0; /* O(1) hash lookup */
if (exists) {
/* Duplicate column found. */
goto dup_err;
}
field->col = table->get_col(j);
- col_added.push_back(j);
+ col_added.insert(j); /* O(1) hash insert */
goto found;
}
@@ -2771,13 +2778,11 @@ static bool dict_index_find_and_set_cols(...) {
if (!strcmp(dict_table_get_v_col_name(table, j), field->name)) {
/* Check if same column is being assigned again
which suggest that column has duplicate name. */
- bool exists = std::find(v_col_added.begin(), v_col_added.end(), j) !=
- v_col_added.end();
+ bool exists = v_col_added.count(j) > 0; /* O(1) hash lookup */
if (exists) {
/* Duplicate column found. */
break;
}
field->col =
reinterpret_cast<dict_col_t *>(dict_table_get_nth_v_col(table, j));
- v_col_added.push_back(j);
+ v_col_added.insert(j); /* O(1) hash insert */
goto found;
}