mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 01:22:04 +00:00
Merge pull request #9028 from Enmk/Gorilla_and_DoubleDelta_buffer_overflow_fix
Fixed buffer overflow on decoding small sequences with Gorilla and DoubleDelta
This commit is contained in:
commit
f4467aaa65
@ -241,30 +241,35 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest)
|
|||||||
|
|
||||||
const char * source_end = source + source_size;
|
const char * source_end = source + source_size;
|
||||||
|
|
||||||
|
if (source + sizeof(UInt32) > source_end)
|
||||||
|
return;
|
||||||
|
|
||||||
const UInt32 items_count = unalignedLoad<UInt32>(source);
|
const UInt32 items_count = unalignedLoad<UInt32>(source);
|
||||||
source += sizeof(items_count);
|
source += sizeof(items_count);
|
||||||
|
|
||||||
ValueType prev_value{};
|
ValueType prev_value{};
|
||||||
UnsignedDeltaType prev_delta{};
|
UnsignedDeltaType prev_delta{};
|
||||||
|
|
||||||
if (source < source_end)
|
// decoding first item
|
||||||
{
|
if (source + sizeof(ValueType) > source_end || items_count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
prev_value = unalignedLoad<ValueType>(source);
|
prev_value = unalignedLoad<ValueType>(source);
|
||||||
unalignedStore<ValueType>(dest, prev_value);
|
unalignedStore<ValueType>(dest, prev_value);
|
||||||
|
|
||||||
source += sizeof(prev_value);
|
source += sizeof(prev_value);
|
||||||
dest += sizeof(prev_value);
|
dest += sizeof(prev_value);
|
||||||
}
|
|
||||||
|
|
||||||
if (source < source_end)
|
// decoding second item
|
||||||
{
|
if (source + sizeof(UnsignedDeltaType) > source_end || items_count < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
prev_delta = unalignedLoad<UnsignedDeltaType>(source);
|
prev_delta = unalignedLoad<UnsignedDeltaType>(source);
|
||||||
prev_value = prev_value + static_cast<ValueType>(prev_delta);
|
prev_value = prev_value + static_cast<ValueType>(prev_delta);
|
||||||
unalignedStore<ValueType>(dest, prev_value);
|
unalignedStore<ValueType>(dest, prev_value);
|
||||||
|
|
||||||
source += sizeof(prev_delta);
|
source += sizeof(prev_delta);
|
||||||
dest += sizeof(prev_value);
|
dest += sizeof(prev_value);
|
||||||
}
|
|
||||||
|
|
||||||
BitReader reader(source, source_size - sizeof(prev_value) - sizeof(prev_delta) - sizeof(items_count));
|
BitReader reader(source, source_size - sizeof(prev_value) - sizeof(prev_delta) - sizeof(items_count));
|
||||||
|
|
||||||
|
@ -159,19 +159,23 @@ void decompressDataForType(const char * source, UInt32 source_size, char * dest)
|
|||||||
|
|
||||||
const char * source_end = source + source_size;
|
const char * source_end = source + source_size;
|
||||||
|
|
||||||
|
if (source + sizeof(UInt32) > source_end)
|
||||||
|
return;
|
||||||
|
|
||||||
const UInt32 items_count = unalignedLoad<UInt32>(source);
|
const UInt32 items_count = unalignedLoad<UInt32>(source);
|
||||||
source += sizeof(items_count);
|
source += sizeof(items_count);
|
||||||
|
|
||||||
T prev_value{};
|
T prev_value{};
|
||||||
|
|
||||||
if (source < source_end)
|
// decoding first item
|
||||||
{
|
if (source + sizeof(T) > source_end || items_count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
prev_value = unalignedLoad<T>(source);
|
prev_value = unalignedLoad<T>(source);
|
||||||
unalignedStore<T>(dest, prev_value);
|
unalignedStore<T>(dest, prev_value);
|
||||||
|
|
||||||
source += sizeof(prev_value);
|
source += sizeof(prev_value);
|
||||||
dest += sizeof(prev_value);
|
dest += sizeof(prev_value);
|
||||||
}
|
|
||||||
|
|
||||||
BitReader reader(source, source_size - sizeof(items_count) - sizeof(prev_value));
|
BitReader reader(source, source_size - sizeof(items_count) - sizeof(prev_value));
|
||||||
|
|
||||||
|
@ -158,8 +158,8 @@ public:
|
|||||||
|
|
||||||
explicit BinaryDataAsSequenceOfValuesIterator(const Container & container_)
|
explicit BinaryDataAsSequenceOfValuesIterator(const Container & container_)
|
||||||
: container(container_),
|
: container(container_),
|
||||||
data(&container[0]),
|
data(container.data()),
|
||||||
data_end(reinterpret_cast<const char *>(data) + container.size()),
|
data_end(container.data() + container.size()),
|
||||||
current_value(T{})
|
current_value(T{})
|
||||||
{
|
{
|
||||||
static_assert(sizeof(container[0]) == 1 && std::is_pod<std::decay_t<decltype(container[0])>>::value, "Only works on containers of byte-size PODs.");
|
static_assert(sizeof(container[0]) == 1 && std::is_pod<std::decay_t<decltype(container[0])>>::value, "Only works on containers of byte-size PODs.");
|
||||||
@ -789,12 +789,14 @@ auto FFand0Generator = []()
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Makes many sequences with generator, first sequence length is 1, second is 2... up to `sequences_count`.
|
// Makes many sequences with generator, first sequence length is 0, second is 1..., third is 2 up to `sequences_count`.
|
||||||
template <typename T, typename Generator>
|
template <typename T, typename Generator>
|
||||||
std::vector<CodecTestSequence> generatePyramidOfSequences(const size_t sequences_count, Generator && generator, const char* generator_name)
|
std::vector<CodecTestSequence> generatePyramidOfSequences(const size_t sequences_count, Generator && generator, const char* generator_name)
|
||||||
{
|
{
|
||||||
std::vector<CodecTestSequence> sequences;
|
std::vector<CodecTestSequence> sequences;
|
||||||
sequences.reserve(sequences_count);
|
sequences.reserve(sequences_count);
|
||||||
|
|
||||||
|
sequences.push_back(makeSeq<T>()); // sequence of size 0
|
||||||
for (size_t i = 1; i < sequences_count; ++i)
|
for (size_t i = 1; i < sequences_count; ++i)
|
||||||
{
|
{
|
||||||
std::string name = generator_name + std::string(" from 0 to ") + std::to_string(i);
|
std::string name = generator_name + std::string(" from 0 to ") + std::to_string(i);
|
||||||
|
Loading…
Reference in New Issue
Block a user