From a2debdb72470fa7d716eb2ad4c8607992c5d0be9 Mon Sep 17 00:00:00 2001 From: Alexey Zatelepin Date: Fri, 15 Mar 2019 21:52:45 +0300 Subject: [PATCH] fix use-after-free [#CLICKHOUSE-3101] --- dbms/programs/server/TCPHandler.h | 2 +- dbms/src/Storages/ColumnsDescription.cpp | 14 ++++++++++++++ dbms/src/Storages/ColumnsDescription.h | 14 +++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/dbms/programs/server/TCPHandler.h b/dbms/programs/server/TCPHandler.h index 38ab27fd67b..a2febf20a20 100644 --- a/dbms/programs/server/TCPHandler.h +++ b/dbms/programs/server/TCPHandler.h @@ -25,7 +25,7 @@ namespace Poco { class Logger; } namespace DB { -struct ColumnsDescription; +class ColumnsDescription; /// State of query processing. struct QueryState diff --git a/dbms/src/Storages/ColumnsDescription.cpp b/dbms/src/Storages/ColumnsDescription.cpp index d3e50e94645..8bb818cd813 100644 --- a/dbms/src/Storages/ColumnsDescription.cpp +++ b/dbms/src/Storages/ColumnsDescription.cpp @@ -111,6 +111,20 @@ ColumnsDescription::ColumnsDescription(NamesAndTypesList ordinary) add(ColumnDescription(std::move(elem.name), std::move(elem.type))); } +ColumnsDescription::ColumnsDescription(const ColumnsDescription & other) + : columns(other.columns) +{ + for (auto it = columns.begin(); it != columns.end(); ++it) + name_to_column.emplace(it->name, it); +} + +ColumnsDescription & ColumnsDescription::operator=(const ColumnsDescription & other) +{ + if (&other != this) + *this = ColumnsDescription(other); + return *this; +} + /// We are trying to find first column from end with name `column_name` or with a name beginning with `column_name` and ".". /// For example "fruits.bananas" diff --git a/dbms/src/Storages/ColumnsDescription.h b/dbms/src/Storages/ColumnsDescription.h index d63d065fa74..8d400c8d1de 100644 --- a/dbms/src/Storages/ColumnsDescription.h +++ b/dbms/src/Storages/ColumnsDescription.h @@ -29,15 +29,15 @@ struct ColumnDescription void readText(ReadBuffer & buf); }; -struct ColumnsDescription +class ColumnsDescription { -private: - std::list columns; - std::unordered_map::iterator> name_to_column; - public: ColumnsDescription() = default; explicit ColumnsDescription(NamesAndTypesList ordinary_); + ColumnsDescription(const ColumnsDescription & other); + ColumnsDescription & operator=(const ColumnsDescription & other); + ColumnsDescription(ColumnsDescription &&) noexcept = default; + ColumnsDescription & operator=(ColumnsDescription &&) noexcept = default; /// `after_column` can be a Nested column name; void add(ColumnDescription column, const String & after_column = String()); @@ -80,6 +80,10 @@ public: static ColumnsDescription parse(const String & str); static const ColumnsDescription * loadFromContext(const Context & context, const String & db, const String & table); + +private: + std::list columns; + std::unordered_map::iterator> name_to_column; }; }