Throw exception in bitTest when position is out of bound

This happens whenever the number of bit positions is bigger
than the number of bits in the number, or when the bit position
is negative.
This commit is contained in:
Pablo Marcos 2024-06-27 08:44:46 +00:00
parent 510924b6b2
commit 146a7e13d9
6 changed files with 42 additions and 5 deletions

View File

@ -8,6 +8,7 @@ namespace DB
namespace ErrorCodes
{
extern const int NOT_IMPLEMENTED;
extern const int PARAMETER_OUT_OF_BOUND;
}
namespace
@ -21,12 +22,21 @@ struct BitTestImpl
static const constexpr bool allow_string_integer = false;
template <typename Result = ResultType>
NO_SANITIZE_UNDEFINED static Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
static Result apply(A a [[maybe_unused]], B b [[maybe_unused]])
{
if constexpr (is_big_int_v<A> || is_big_int_v<B>)
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "bitTest is not implemented for big integers as second argument");
else
return (typename NumberTraits::ToInteger<A>::Type(a) >> typename NumberTraits::ToInteger<B>::Type(b)) & 1;
{
const auto max_position = decltype(b)((8 * sizeof(a)) - 1);
if (b > max_position || b < 0)
{
throw Exception(ErrorCodes::PARAMETER_OUT_OF_BOUND,
"The bit position argument needs to a positive value and less or equal to {} for integer {}",
static_cast<Int16>(max_position), static_cast<Int64>(a));
}
return (a >> b) & 1;
}
}
#if USE_EMBEDDED_COMPILER

View File

@ -1 +0,0 @@
SELECT sum(ignore(bitTest(number, 65))) FROM numbers(10);

View File

@ -198,3 +198,27 @@
97 1
98 1
99 1
0 1
1 0
2 1
3 0
4 1
5 0
6 1
7 0
0 1
1 0
2 1
3 0
4 1
5 0
6 1
7 0
8 1
9 0
10 1
11 0
12 1
13 0
14 1
15 0

View File

@ -1,2 +1,7 @@
SELECT number, bitTestAny(toUInt8(1 + 4 + 16 + 64), number) FROM numbers(100);
SELECT number, bitTestAll(toUInt8(1 + 4 + 16 + 64), number) FROM numbers(100);
SELECT number, bitTest(toUInt8(1 + 4 + 16 + 64), number) FROM numbers(8);
SELECT number, bitTest(toUInt8(1 + 4 + 16 + 64), number) FROM numbers(8, 16); -- { serverError PARAMETER_OUT_OF_BOUND }
SELECT number, bitTest(toUInt16(1 + 4 + 16 + 64 + 256 + 1024 + 4096 + 16384 + 65536), number) FROM numbers(16);
SELECT -number, bitTest(toUInt16(1), -number) FROM numbers(8); -- { serverError PARAMETER_OUT_OF_BOUND }

View File

@ -16,7 +16,7 @@ select min(i), max(i), count() from d where _partition_value.1 = 10 group by _pa
select min(i) from d where 1 = _partition_value.1;
-- fuzz crash https://github.com/ClickHouse/ClickHouse/issues/37151
SELECT min(i), max(i), count() FROM d WHERE (_partition_value.1) = 0 GROUP BY ignore(bitTest(ignore(NULL), 65535), NULL, (_partition_value.1) = 7, '10.25', bitTest(NULL, -9223372036854775808), NULL, ignore(ignore(-2147483647, NULL)), 1024), _partition_id ORDER BY _partition_id ASC NULLS FIRST;
SELECT min(i), max(i), count() FROM d WHERE (_partition_value.1) = 0 GROUP BY ignore(bitTest(ignore(NULL), 0), NULL, (_partition_value.1) = 7, '10.25', bitTest(NULL, 0), NULL, ignore(ignore(-2147483647, NULL)), 1024), _partition_id ORDER BY _partition_id ASC NULLS FIRST;
drop table d;