Protect against DOS

This commit is contained in:
Robert Schulze 2023-05-23 12:16:49 +00:00
parent b106757a3c
commit 285e8f4ae1
No known key found for this signature in database
GPG Key ID: 26703B55FB13728A
3 changed files with 17 additions and 5 deletions

View File

@ -24,18 +24,16 @@ struct RepeatImpl
/// Safety threshold against DoS. /// Safety threshold against DoS.
static inline void checkRepeatTime(UInt64 repeat_time) static inline void checkRepeatTime(UInt64 repeat_time)
{ {
static constexpr UInt64 max_repeat_times = 1000000; static constexpr UInt64 max_repeat_times = 1'000'000;
if (repeat_time > max_repeat_times) if (repeat_time > max_repeat_times)
throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "Too many times to repeat ({}), maximum is: {}", throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "Too many times to repeat ({}), maximum is: {}", repeat_time, max_repeat_times);
std::to_string(repeat_time), std::to_string(max_repeat_times));
} }
static inline void checkStringSize(UInt64 size) static inline void checkStringSize(UInt64 size)
{ {
static constexpr UInt64 max_string_size = 1 << 30; static constexpr UInt64 max_string_size = 1 << 30;
if (size > max_string_size) if (size > max_string_size)
throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "Too large string size ({}) in function repeat, maximum is: {}", throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "Too large string size ({}) in function repeat, maximum is: {}", size, max_string_size);
size, max_string_size);
} }
template <typename T> template <typename T>

View File

@ -13,6 +13,7 @@ namespace DB
namespace ErrorCodes namespace ErrorCodes
{ {
extern const int ILLEGAL_COLUMN; extern const int ILLEGAL_COLUMN;
extern const int TOO_LARGE_STRING_SIZE;
} }
namespace namespace
@ -25,6 +26,14 @@ class FunctionSpace : public IFunction
private: private:
static constexpr auto space = ' '; static constexpr auto space = ' ';
/// Safety threshold against DoS.
static inline void checkRepeatTime(UInt64 repeat_time)
{
static constexpr UInt64 max_repeat_times = 1'000'000;
if (repeat_time > max_repeat_times)
throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "Too many times to repeat ({}), maximum is: {}", repeat_time, max_repeat_times);
}
public: public:
static constexpr auto name = "space"; static constexpr auto name = "space";
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionSpace>(); } static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionSpace>(); }
@ -60,6 +69,8 @@ public:
if (times < 1) if (times < 1)
times = 0; times = 0;
checkRepeatTime(times);
res_offsets.resize(col_times->size()); res_offsets.resize(col_times->size());
res_chars.resize(col_times->size() * (times + 1)); res_chars.resize(col_times->size() * (times + 1));
@ -101,6 +112,8 @@ public:
if (times < 1) if (times < 1)
times = 0; times = 0;
checkRepeatTime(times);
if (res_chars.size() + times + 1 >= res_chars.capacity()) if (res_chars.size() + times + 1 >= res_chars.capacity())
res_chars.resize(2 * res_chars.capacity()); res_chars.resize(2 * res_chars.capacity());

View File

@ -19,6 +19,7 @@ SELECT 'negative tests';
SELECT space('abc'); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT } SELECT space('abc'); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT space(['abc']); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT } SELECT space(['abc']); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT space(('abc')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT } SELECT space(('abc')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT space(30303030303030303030303030303030::UInt64); -- { serverError TOO_LARGE_STRING_SIZE }
SELECT 'null'; SELECT 'null';
SELECT space(NULL); SELECT space(NULL);