62 lines
2.5 KiB
Diff
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;
|
|
}
|