提交 29073854 编写于 作者: A Azat Khuzhin

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<DB::ColumnWithTypeAndName, std::__1::allocator<DB::ColumnWithTypeAndName> >::back() @ 0x128c07a6 in /workspace/clickhouse
./obj-x86_64-linux-gnu/../src/Dictionaries/RangeDictionaryBlockInputStream.h:0: DB::RangeDictionaryBlockInputStream<DB::RangeHashedDictionary, unsigned short, unsigned long>::fillBlock(DB::PODArray<unsigned long, 4096ul, Allocator<false, false>, 15ul, 16ul> const&, DB::PODArray<unsigned short, 4096ul, Allocator<false, false>, 15ul, 16ul> const&, DB::PODArray<unsigned short, 4096ul, Allocator<false, false>, 15ul, 16ul> const&) const @ 0x1692335e in /workspace/clickhouse
./obj-x86_64-linux-gnu/../src/Dictionaries/RangeDictionaryBlockInputStream.h:0: DB::RangeDictionaryBlockInputStream<DB::RangeHashedDictionary, unsigned short, unsigned long>::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
上级 d88f7bc0
...@@ -47,7 +47,8 @@ private: ...@@ -47,7 +47,8 @@ private:
const std::string & default_name, const std::string & default_name,
const std::unordered_set<std::string> & column_names_set, const std::unordered_set<std::string> & column_names_set,
const PaddedPODArray<T> & values, const PaddedPODArray<T> & values,
ColumnsWithTypeAndName & columns) const; ColumnsWithTypeAndName & columns,
bool force = false) const;
Block fillBlock( Block fillBlock(
const PaddedPODArray<Key> & ids_to_fill, const PaddedPODArray<Key> & ids_to_fill,
...@@ -121,13 +122,14 @@ void RangeDictionaryBlockInputStream<DictionaryType, RangeType, Key>::addSpecial ...@@ -121,13 +122,14 @@ void RangeDictionaryBlockInputStream<DictionaryType, RangeType, Key>::addSpecial
const std::string & default_name, const std::string & default_name,
const std::unordered_set<std::string> & column_names_set, const std::unordered_set<std::string> & column_names_set,
const PaddedPODArray<T> & values, const PaddedPODArray<T> & values,
ColumnsWithTypeAndName & columns) const ColumnsWithTypeAndName & columns,
bool force) const
{ {
std::string name = default_name; std::string name = default_name;
if (attribute) if (attribute)
name = attribute->name; 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); columns.emplace_back(getColumnFromPODArray(values), type, name);
} }
...@@ -159,7 +161,7 @@ Block RangeDictionaryBlockInputStream<DictionaryType, RangeType, Key>::fillBlock ...@@ -159,7 +161,7 @@ Block RangeDictionaryBlockInputStream<DictionaryType, RangeType, Key>::fillBlock
std::unordered_set<std::string> names(column_names.begin(), column_names.end()); std::unordered_set<std::string> names(column_names.begin(), column_names.end());
addSpecialColumn(structure.id, std::make_shared<DataTypeUInt64>(), "ID", names, ids_to_fill, columns); addSpecialColumn(structure.id, std::make_shared<DataTypeUInt64>(), "ID", names, ids_to_fill, columns, true);
auto ids_column = columns.back().column; auto ids_column = columns.back().column;
addSpecialColumn(structure.range_min, structure.range_max->type, "Range Start", names, block_start_dates, columns); 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); addSpecialColumn(structure.range_max, structure.range_max->type, "Range End", names, block_end_dates, columns);
......
1 2019-01-05 2020-01-10 1 1 2019-01-05 2020-01-10 1
1
date_table date_table
somedict somedict
...@@ -29,6 +29,9 @@ LIFETIME(MIN 300 MAX 360); ...@@ -29,6 +29,9 @@ LIFETIME(MIN 300 MAX 360);
SELECT * from somedict; SELECT * from somedict;
-- No dictionary columns
SELECT 1 FROM somedict;
SHOW TABLES; SHOW TABLES;
DROP DATABASE IF EXISTS database_for_dict; DROP DATABASE database_for_dict;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册