From 07f4bfc844b909fa3b9b6ff24688349959ed6b13 Mon Sep 17 00:00:00 2001 From: Vitaliy Lyudvichenko Date: Thu, 27 Oct 2016 17:51:43 +0300 Subject: [PATCH] Fixed segfaults in quantiles* functions with empty levels set. [#METR-23285] --- .../AggregateFunctionQuantileExactWeighted.h | 3 +++ .../AggregateFunctions/AggregateFunctionQuantileTDigest.h | 6 ++++++ .../AggregateFunctions/AggregateFunctionQuantileTiming.h | 6 ++++++ .../00382_quantiles_empty_levels_segfaults.reference | 8 ++++++++ .../00382_quantiles_empty_levels_segfaults.sql | 8 ++++++++ 5 files changed, 31 insertions(+) create mode 100644 dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.reference create mode 100644 dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.sql diff --git a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileExactWeighted.h b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileExactWeighted.h index 0f4a963b1c4..ebc7c8d0e6a 100644 --- a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileExactWeighted.h +++ b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileExactWeighted.h @@ -233,6 +233,9 @@ public: size_t num_levels = levels.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + num_levels); + if (!num_levels) + return; + typename ColumnVector::Container_t & data_to = static_cast &>(arr_to.getData()).getData(); size_t old_size = data_to.size(); diff --git a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTDigest.h b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTDigest.h index 7f82de744ec..6be35062d0c 100644 --- a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTDigest.h +++ b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTDigest.h @@ -541,6 +541,9 @@ public: size_t size = levels.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size); + if (!size) + return; + if (returns_float) { typename ColumnFloat32::Container_t & data_to = static_cast(arr_to.getData()).getData(); @@ -623,6 +626,9 @@ public: size_t size = levels.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size); + if (!size) + return; + if (returns_float) { typename ColumnFloat32::Container_t & data_to = static_cast(arr_to.getData()).getData(); diff --git a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTiming.h b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTiming.h index b659d4b7282..d854522d230 100644 --- a/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTiming.h +++ b/dbms/include/DB/AggregateFunctions/AggregateFunctionQuantileTiming.h @@ -958,6 +958,9 @@ public: size_t size = levels.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size); + if (!size) + return; + typename ColumnFloat32::Container_t & data_to = static_cast(arr_to.getData()).getData(); size_t old_size = data_to.size(); data_to.resize(data_to.size() + size); @@ -1021,6 +1024,9 @@ public: size_t size = levels.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size); + if (!size) + return; + typename ColumnFloat32::Container_t & data_to = static_cast(arr_to.getData()).getData(); size_t old_size = data_to.size(); data_to.resize(data_to.size() + size); diff --git a/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.reference b/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.reference new file mode 100644 index 00000000000..3804f8a692d --- /dev/null +++ b/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.reference @@ -0,0 +1,8 @@ +[] +[] +[] +[] +[] +[] +[] +[] diff --git a/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.sql b/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.sql new file mode 100644 index 00000000000..dfacd78b962 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00382_quantiles_empty_levels_segfaults.sql @@ -0,0 +1,8 @@ +select quantiles(number) as q from (select * from system.numbers LIMIT 1000); +select quantilesExact(number) as q from (select * from system.numbers LIMIT 1000); +select quantilesExactWeighted(number, number) as q from (select * from system.numbers LIMIT 1000); +select quantilesDeterministic(number, 10000000) as q from (select * from system.numbers LIMIT 1000); +select quantilesTiming(number) as q from (select * from system.numbers LIMIT 1000); +select quantilesTimingWeighted(number, number) as q from (select * from system.numbers LIMIT 1000); +select quantilesTDigest(number) as q from (select * from system.numbers LIMIT 1000); +select quantilesTDigestWeighted(number, number) as q from (select * from system.numbers LIMIT 1000);