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
This commit is contained in:
Azat Khuzhin 2021-09-09 08:45:05 +03:00
parent 5b967d91ba
commit 62a29420bd
3 changed files with 20 additions and 11 deletions

View File

@ -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<Int64>() - 1;
transform->current_row.row].get<Int64>();
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

View File

@ -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;

View File

@ -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;