Fix UBsan reports in quantileTiming

UBsan reports [1]:

    ../src/AggregateFunctions/QuantileTiming.h:442:27: runtime error: 1.84467e+19 is outside the range of representable values of type 'unsigned long' Received signal -3 Received signal Unknown signal (-3)

  [1]: https://clickhouse-test-reports.s3.yandex.net/19971/e15f5d9cb5b36482d1ae9ca069074fb200f2ab37/fuzzer_ubsan/report.html#fail1

Follow-up for: #19394
This commit is contained in:
Azat Khuzhin 2021-02-02 23:31:03 +03:00
parent da79469092
commit 984445b44b
3 changed files with 39 additions and 4 deletions

View File

@ -32,6 +32,8 @@ namespace ErrorCodes
* - a histogram (that is, value -> number), consisting of two parts
* -- for values from 0 to 1023 - in increments of 1;
* -- for values from 1024 to 30,000 - in increments of 16;
*
* NOTE: 64-bit integer weight can overflow, see also QantileExactWeighted.h::get()
*/
#define TINY_MAX_ELEMS 31
@ -396,9 +398,9 @@ namespace detail
/// Get the value of the `level` quantile. The level must be between 0 and 1.
UInt16 get(double level) const
{
UInt64 pos = std::ceil(count * level);
double pos = std::ceil(count * level);
UInt64 accumulated = 0;
double accumulated = 0;
Iterator it(*this);
while (it.isValid())
@ -422,9 +424,9 @@ namespace detail
const auto * indices_end = indices + size;
const auto * index = indices;
UInt64 pos = std::ceil(count * levels[*index]);
double pos = std::ceil(count * levels[*index]);
UInt64 accumulated = 0;
double accumulated = 0;
Iterator it(*this);
while (it.isValid())

View File

@ -0,0 +1,2 @@
[0]
[0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1]

View File

@ -0,0 +1,31 @@
-- NOTE: that due to overflows it may give different result before
-- quantilesTimingWeighted() had been converted to double:
--
-- Before:
--
-- SELECT quantilesTimingWeighted(1)(number, 9223372036854775807)
-- FROM numbers(2)
--
-- ┌─quantilesTimingWeighted(1)(number, 9223372036854775807)─┐
-- │ [1] │
-- └─────────────────────────────────────────────────────────┘
--
-- After:
--
-- SELECT quantilesTimingWeighted(1)(number, 9223372036854775807)
-- FROM numbers(2)
--
-- ┌─quantilesTimingWeighted(1)(number, 9223372036854775807)─┐
-- │ [0] │
-- └─────────────────────────────────────────────────────────┘
SELECT quantilesTimingWeighted(0.1)(number, 9223372036854775807) FROM numbers(2);
-- same UB, but in the inner loop
SELECT quantilesTimingWeighted(0, 0.001, 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99, 0.999, 1)(number, 9223372036854775807)
FROM
(
SELECT number
FROM system.numbers
LIMIT 100
);