# UNDF: UNDF-2026-000000161 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -29057,12 +29057,22 @@ setup_new_fields(THD *thd, List &fields, List &all_fields, ORDER *new_field) { Item **item; uint counter; enum_resolution_type not_used; DBUG_ENTER("setup_new_fields"); thd->column_usage= MARK_COLUMNS_READ; // Not really needed, but... + // CWE-407 fix (mariadb-0002): build name->item* map once before the loop. + // find_item_in_list is O(S) per call; with N new fields this is O(N*S). + // An upfront index reduces the loop body to O(1) for name-matched items. + std::unordered_map field_index; + { + List_iterator idx_it(fields); + Item *idx_item; + uint idx_pos = 0; + while ((idx_item = idx_it++)) { + if (idx_item->item_name.is_set()) + field_index[std::string(idx_item->item_name.ptr())] = + fields.elem(idx_pos); + ++idx_pos; + } + } for (; new_field ; new_field= new_field->next) { - if ((item= find_item_in_list(*new_field->item, fields, &counter, - IGNORE_ERRORS, ¬_used))) + // Fast path: O(1) name lookup via pre-built index + std::string lookup_name; + if ((*new_field->item)->item_name.is_set()) + lookup_name = (*new_field->item)->item_name.ptr(); + auto fast = (!lookup_name.empty()) ? field_index.find(lookup_name) + : field_index.end(); + if (fast != field_index.end()) { + item = fast->second; + } else if ((item= find_item_in_list(*new_field->item, fields, &counter, + IGNORE_ERRORS, ¬_used))) { + // fallback to linear scan for alias/table-qualified names + } else { + item = nullptr; + } + if (item) new_field->item=item; /* Change to shared Item */ else {