64 lines
2.9 KiB
Diff
64 lines
2.9 KiB
Diff
# UNDF: UNDF-2026-000000031
|
||
diff --git a/src/Analyzer/ColumnTransformers.cpp b/src/Analyzer/ColumnTransformers.cpp
|
||
index d5484e6c..5632ba67 100644
|
||
--- a/src/Analyzer/ColumnTransformers.cpp
|
||
+++ b/src/Analyzer/ColumnTransformers.cpp
|
||
@@ -264,20 +264,23 @@ ReplaceColumnTransformerNode::ReplaceColumnTransformerNode(const std::vector<Rep
|
||
"Expressions in column transformer replace should not contain same replacement {} more than once",
|
||
replacement.column_name);
|
||
|
||
+ size_t new_index = replacements_names.size();
|
||
replacements_names.push_back(replacement.column_name);
|
||
+ replacements_index.emplace(replacement.column_name, new_index);
|
||
replacement_expressions_nodes.push_back(replacement.expression_node);
|
||
}
|
||
}
|
||
|
||
QueryTreeNodePtr ReplaceColumnTransformerNode::findReplacementExpression(const std::string & expression_name)
|
||
{
|
||
- auto it = std::find(replacements_names.begin(), replacements_names.end(), expression_name);
|
||
- if (it == replacements_names.end())
|
||
+ // CWE-407 fix: O(1) hash-map lookup replaces O(n) std::find scan over replacements_names.
|
||
+ // Called inside a O(columns × transformers) nested loop in QueryAnalyzer::resolveColumnsTransformers().
|
||
+ auto idx_it = replacements_index.find(expression_name);
|
||
+ if (idx_it == replacements_index.end())
|
||
return {};
|
||
|
||
- size_t replacement_index = it - replacements_names.begin();
|
||
auto & replacement_expressions_nodes = getReplacements().getNodes();
|
||
- return replacement_expressions_nodes[replacement_index];
|
||
+ return replacement_expressions_nodes[idx_it->second];
|
||
}
|
||
|
||
void ReplaceColumnTransformerNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const
|
||
@@ -329,6 +332,7 @@ QueryTreeNodePtr ReplaceColumnTransformerNode::cloneImpl() const
|
||
|
||
result_replace_transformer->is_strict = is_strict;
|
||
result_replace_transformer->replacements_names = replacements_names;
|
||
+ result_replace_transformer->replacements_index = replacements_index;
|
||
|
||
return result_replace_transformer;
|
||
}
|
||
diff --git a/src/Analyzer/ColumnTransformers.h b/src/Analyzer/ColumnTransformers.h
|
||
index 406f8ddd..68d37970 100644
|
||
--- a/src/Analyzer/ColumnTransformers.h
|
||
+++ b/src/Analyzer/ColumnTransformers.h
|
||
@@ -3,6 +3,7 @@
|
||
#include <Analyzer/IQueryTreeNode.h>
|
||
#include <Analyzer/ListNode.h>
|
||
#include <Core/Names.h>
|
||
+#include <unordered_map>
|
||
|
||
namespace re2
|
||
{
|
||
@@ -304,6 +305,10 @@ private:
|
||
}
|
||
|
||
Names replacements_names;
|
||
+ // CWE-407 fix: shadow map for O(1) name→index lookup in findReplacementExpression(),
|
||
+ // replacing the O(n) std::find scan over replacements_names that was called in the
|
||
+ // O(columns × transformers) nested loop in QueryAnalyzer::resolveColumnsTransformers().
|
||
+ std::unordered_map<std::string, size_t> replacements_index;
|
||
bool is_strict = false;
|
||
|
||
static constexpr size_t replacements_child_index = 0;
|