From 62a29420bd0baa61bd0598e2c7bdc6fc15976707 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Thu, 9 Sep 2021 08:45:05 +0300 Subject: [PATCH] Fix signed integer overflow for nth_value() window function CI report [1]: ../src/Processors/Transforms/WindowTransform.cpp:1699:54: runtime error: signed integer overflow: -9223372036854775808 - 1 cannot be represented in type 'long' Received signal -3 Received signal Unknown signal (-3) In query: SELECT number, nth_value(number, 2147483648) OVER w, anyOrNull(number) OVER (ORDER BY -2147483648 - intDiv(number, 1024) DESC NULLS FIRST, number DESC ROWS BETWEEN 65535 FOLLOWING AND UNBOUNDED FOLLOWING), nth_value(number, 65537) OVER w AS firstValue, nth_value(number, -9223372036854775808) OVER w AS secondValue, nth_value(number, 1048576) OVER w AS thirdValue FROM numbers(1) WINDOW w AS (ORDER BY number DESC) ORDER BY number DESC [1]: https://clickhouse-test-reports.s3.yandex.net/28532/7623af5513e12aa8dfa1bee963caffe00185c31a/fuzzer_ubsan/report.html#fail1 --- src/Processors/Transforms/WindowTransform.cpp | 14 ++++---------- .../0_stateless/01591_window_functions.reference | 8 ++++++++ .../queries/0_stateless/01591_window_functions.sql | 9 ++++++++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Processors/Transforms/WindowTransform.cpp b/src/Processors/Transforms/WindowTransform.cpp index 132bdb7b327..b685248be01 100644 --- a/src/Processors/Transforms/WindowTransform.cpp +++ b/src/Processors/Transforms/WindowTransform.cpp @@ -1696,22 +1696,16 @@ struct WindowFunctionNthValue final : public WindowFunction int64_t offset = (*current_block.input_columns[ workspace.argument_column_indices[1]])[ - transform->current_row.row].get() - 1; + transform->current_row.row].get(); - if (offset < 0) + if (offset > INT_MAX || offset <= 0) { throw Exception(ErrorCodes::BAD_ARGUMENTS, - "The offset for function {} must be non-negative, {} given", - getName(), offset); - } - - if (offset > INT_MAX) - { - throw Exception(ErrorCodes::BAD_ARGUMENTS, - "The offset for function {} must be less than {}, {} given", + "The offset for function {} must be in (0, {}], {} given", getName(), INT_MAX, offset); } + --offset; const auto [target_row, offset_left] = transform->moveRowNumber(transform->frame_start, offset); if (offset_left != 0 || target_row < transform->frame_start diff --git a/tests/queries/0_stateless/01591_window_functions.reference b/tests/queries/0_stateless/01591_window_functions.reference index 26e9e500c3c..48f6a91b92a 100644 --- a/tests/queries/0_stateless/01591_window_functions.reference +++ b/tests/queries/0_stateless/01591_window_functions.reference @@ -1150,6 +1150,14 @@ WINDOW w AS (ORDER BY number ASC) 2 0 2 3 0 2 4 0 2 +-- UBsan +SELECT nth_value(number, -9223372036854775808) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, 0) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, /* INT_MAX+1 */ 2147483648) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, /* INT_MAX */ 2147483647) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); +0 +SELECT nth_value(number, 1) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); +0 -- In this case, we had a problem with PartialSortingTransform returning zero-row -- chunks for input chunks w/o columns. select count() over () from numbers(4) where number < 2; diff --git a/tests/queries/0_stateless/01591_window_functions.sql b/tests/queries/0_stateless/01591_window_functions.sql index 3075c1ddb46..1004f80efce 100644 --- a/tests/queries/0_stateless/01591_window_functions.sql +++ b/tests/queries/0_stateless/01591_window_functions.sql @@ -434,7 +434,14 @@ SELECT FROM numbers(5) WINDOW w AS (ORDER BY number ASC) ; - + +-- UBsan +SELECT nth_value(number, -9223372036854775808) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, 0) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, /* INT_MAX+1 */ 2147483648) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); -- { serverError BAD_ARGUMENTS } +SELECT nth_value(number, /* INT_MAX */ 2147483647) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); +SELECT nth_value(number, 1) OVER w AS v FROM numbers(1) WINDOW w AS (ORDER BY number DESC); + -- In this case, we had a problem with PartialSortingTransform returning zero-row -- chunks for input chunks w/o columns. select count() over () from numbers(4) where number < 2;