From 29073854009e3894113e5693093236376c68b8e4 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Thu, 11 Feb 2021 21:07:37 +0300 Subject: [PATCH] Avoid invalid dereference in RANGE_HASHED() dictionary UBsan report the following [1], when query does not contains any columns from the dictionary: ```sql SELECT toUInt32(toUInt32(NULL, toUInt32(NULL, inf, NULL), NULL)), toUInt32(toUInt32(toUInt32(toUInt32(toUInt32(NULL, 1., NULL)), toUInt32(toUInt32(NULL, 0.5, NULL)), toUInt32(NULL, NULL)), toUInt32(toUInt32(NULL, 1., NULL)), toUInt32(NULL, NULL)), toUInt32(toUInt32(toUInt32(toUInt32(NULL, 1000.0001220703125, NULL)), toUInt32(toUInt32(NULL, 10.000100135803223, NULL)), toUInt32(NULL, NULL)), NULL, NULL, NULL)) FROM somedict ``` ``` std::__1::vector >::back() @ 0x128c07a6 in /workspace/clickhouse ./obj-x86_64-linux-gnu/../src/Dictionaries/RangeDictionaryBlockInputStream.h:0: DB::RangeDictionaryBlockInputStream::fillBlock(DB::PODArray, 15ul, 16ul> const&, DB::PODArray, 15ul, 16ul> const&, DB::PODArray, 15ul, 16ul> const&) const @ 0x1692335e in /workspace/clickhouse ./obj-x86_64-linux-gnu/../src/Dictionaries/RangeDictionaryBlockInputStream.h:0: DB::RangeDictionaryBlockInputStream::getBlock(unsigned long, unsigned long) const @ 0x16922f96 in /workspace/clickhouse ./obj-x86_64-linux-gnu/../src/Dictionaries/DictionaryBlockInputStreamBase.cpp:23: DB::DictionaryBlockInputStreamBase::getHeader() const @ 0x166ab57c in /workspace/clickhouse ``` [1]: https://clickhouse-test-reports.s3.yandex.net/19451/64c0bf98290362fa216c05b070aa122a12af3c25/fuzzer_ubsan/report.html#fail1 --- src/Dictionaries/RangeDictionaryBlockInputStream.h | 10 ++++++---- .../01125_dict_ddl_cannot_add_column.reference | 1 + .../0_stateless/01125_dict_ddl_cannot_add_column.sql | 5 ++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Dictionaries/RangeDictionaryBlockInputStream.h b/src/Dictionaries/RangeDictionaryBlockInputStream.h index 3da43c85c45..ccd77d49e0f 100644 --- a/src/Dictionaries/RangeDictionaryBlockInputStream.h +++ b/src/Dictionaries/RangeDictionaryBlockInputStream.h @@ -47,7 +47,8 @@ private: const std::string & default_name, const std::unordered_set & column_names_set, const PaddedPODArray & values, - ColumnsWithTypeAndName & columns) const; + ColumnsWithTypeAndName & columns, + bool force = false) const; Block fillBlock( const PaddedPODArray & ids_to_fill, @@ -121,13 +122,14 @@ void RangeDictionaryBlockInputStream::addSpecial const std::string & default_name, const std::unordered_set & column_names_set, const PaddedPODArray & values, - ColumnsWithTypeAndName & columns) const + ColumnsWithTypeAndName & columns, + bool force) const { std::string name = default_name; if (attribute) name = attribute->name; - if (column_names_set.find(name) != column_names_set.end()) + if (force || column_names_set.find(name) != column_names_set.end()) columns.emplace_back(getColumnFromPODArray(values), type, name); } @@ -159,7 +161,7 @@ Block RangeDictionaryBlockInputStream::fillBlock std::unordered_set names(column_names.begin(), column_names.end()); - addSpecialColumn(structure.id, std::make_shared(), "ID", names, ids_to_fill, columns); + addSpecialColumn(structure.id, std::make_shared(), "ID", names, ids_to_fill, columns, true); auto ids_column = columns.back().column; addSpecialColumn(structure.range_min, structure.range_max->type, "Range Start", names, block_start_dates, columns); addSpecialColumn(structure.range_max, structure.range_max->type, "Range End", names, block_end_dates, columns); diff --git a/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.reference b/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.reference index 1a9e5685a6a..71be9c3fb5b 100644 --- a/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.reference +++ b/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.reference @@ -1,3 +1,4 @@ 1 2019-01-05 2020-01-10 1 +1 date_table somedict diff --git a/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.sql b/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.sql index 6ad76ee5a7e..471fd7959a9 100644 --- a/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.sql +++ b/tests/queries/0_stateless/01125_dict_ddl_cannot_add_column.sql @@ -29,6 +29,9 @@ LIFETIME(MIN 300 MAX 360); SELECT * from somedict; +-- No dictionary columns +SELECT 1 FROM somedict; + SHOW TABLES; -DROP DATABASE IF EXISTS database_for_dict; +DROP DATABASE database_for_dict;