mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
First blood
This commit is contained in:
parent
4685fb4226
commit
e63da5969f
39
src/Common/examples/YAML_fuzzer.cpp
Normal file
39
src/Common/examples/YAML_fuzzer.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <time.h>
|
||||
#include <filesystem>
|
||||
|
||||
#include <Common/Config/YAMLParser.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
|
||||
{
|
||||
/// How to test:
|
||||
/// build ClickHouse with YAML_fuzzer.cpp
|
||||
/// ./YAML_fuzzer YAML_CORPUS
|
||||
/// where YAML_CORPUS is a directory with different YAML configs for libfuzzer
|
||||
char file_name[L_tmpnam];
|
||||
if (!std::tmpnam(file_name))
|
||||
{
|
||||
std::cerr << "Cannot create temp file!\n";
|
||||
return 1;
|
||||
}
|
||||
std::string input = std::string(reinterpret_cast<const char*>(data), size);
|
||||
|
||||
{
|
||||
std::ofstream temp_file(file_name);
|
||||
temp_file << input;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
DB::YAMLParserImpl::parse(std::string(file_name));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "YAML_fuzzer failed: " << DB::getCurrentExceptionMessage(__PRETTY_FUNCTION__) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,14 +1,3 @@
|
||||
if (ENABLE_FUZZING)
|
||||
include("${ClickHouse_SOURCE_DIR}/cmake/dbms_glob_sources.cmake")
|
||||
add_headers_and_sources(fuzz_compression .)
|
||||
|
||||
# Remove this file, because it has dependencies on DataTypes
|
||||
list(REMOVE_ITEM ${fuzz_compression_sources} CompressionFactoryAdditions.cpp)
|
||||
|
||||
add_library(fuzz_compression ${fuzz_compression_headers} ${fuzz_compression_sources})
|
||||
target_link_libraries(fuzz_compression PUBLIC clickhouse_parsers clickhouse_common_io common lz4)
|
||||
endif()
|
||||
|
||||
if (ENABLE_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
@ -209,4 +209,10 @@ void registerCodecDelta(CompressionCodecFactory & factory)
|
||||
return std::make_shared<CompressionCodecDelta>(delta_bytes_size);
|
||||
});
|
||||
}
|
||||
|
||||
CompressionCodecPtr getCompressionCodecDelta(UInt8 delta_bytes_size)
|
||||
{
|
||||
return std::make_shared<CompressionCodecDelta>(delta_bytes_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -543,4 +543,5 @@ void registerCodecDoubleDelta(CompressionCodecFactory & factory)
|
||||
return std::make_shared<CompressionCodecDoubleDelta>(data_bytes_size);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -147,4 +147,10 @@ CompressionCodecLZ4HC::CompressionCodecLZ4HC(int level_)
|
||||
setCodecDescription("LZ4HC", {std::make_shared<ASTLiteral>(static_cast<UInt64>(level))});
|
||||
}
|
||||
|
||||
|
||||
CompressionCodecPtr getCompressionCodecLZ4(int level)
|
||||
{
|
||||
return std::make_shared<CompressionCodecLZ4HC>(level);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ using Codecs = std::vector<CompressionCodecPtr>;
|
||||
|
||||
class IDataType;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size);
|
||||
|
||||
/**
|
||||
* Represents interface for compression codecs like LZ4, ZSTD, etc.
|
||||
*/
|
||||
@ -85,6 +87,8 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
friend int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size);
|
||||
|
||||
/// Return size of compressed data without header
|
||||
virtual UInt32 getMaxCompressedDataSize(UInt32 uncompressed_size) const { return uncompressed_size; }
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
add_executable (compressed_buffer_fuzzer compressed_buffer_fuzzer.cpp)
|
||||
|
||||
# Our code has strong cohesion and target associated with `Compression` also depends on `DataTypes`.
|
||||
# But we can exclude some files which have dependencies in case of
|
||||
# fuzzer related build (we are interested in fuzzing only particular part of our code).
|
||||
# So, some symbols will be declared, but not defined. Unfortunately, this trick doesn't work with UBSan.
|
||||
# If you want really small size of the resulted binary, just link with fuzz_compression and clickhouse_common_io
|
||||
|
||||
add_executable (compressed_buffer_fuzzer compressed_buffer_fuzzer.cpp)
|
||||
target_link_libraries (compressed_buffer_fuzzer PRIVATE dbms ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable (lz4_decompress_fuzzer lz4_decompress_fuzzer.cpp)
|
||||
target_link_libraries (lz4_decompress_fuzzer PRIVATE dbms ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable (delta_decompress_fuzzer delta_decompress_fuzzer.cpp)
|
||||
target_link_libraries (delta_decompress_fuzzer PRIVATE dbms ${LIB_FUZZING_ENGINE})
|
||||
|
47
src/Compression/fuzzers/delta_decompress_fuzzer.cpp
Normal file
47
src/Compression/fuzzers/delta_decompress_fuzzer.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <Compression/ICompressionCodec.h>
|
||||
#include <IO/BufferWithOwnMemory.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
CompressionCodecPtr getCompressionCodecDelta(UInt8 delta_bytes_size);
|
||||
}
|
||||
|
||||
struct AuxiliaryRandomData
|
||||
{
|
||||
UInt8 delta_size_bytes;
|
||||
size_t decompressed_size;
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
|
||||
try
|
||||
{
|
||||
if (size < sizeof(AuxiliaryRandomData))
|
||||
return 0;
|
||||
|
||||
auto * p = reinterpret_cast<const AuxiliaryRandomData *>(data);
|
||||
auto codec = DB::getCompressionCodecDelta(p->delta_size_bytes);
|
||||
|
||||
size_t output_buffer_size = p->decompressed_size % 65536;
|
||||
size -= sizeof(AuxiliaryRandomData);
|
||||
data += sizeof(AuxiliaryRandomData) / sizeof(uint8_t);
|
||||
|
||||
std::string input = std::string(reinterpret_cast<const char*>(data), size);
|
||||
fmt::print(stderr, "Using input {} of size {}, output size is {}. \n", input, size, output_buffer_size);
|
||||
|
||||
if (output_buffer_size < size)
|
||||
return 0;
|
||||
|
||||
DB::Memory<> memory;
|
||||
memory.resize(output_buffer_size + codec->getAdditionalSizeAtTheEndOfBuffer());
|
||||
|
||||
codec->doDecompressData(reinterpret_cast<const char *>(data), size, memory.data(), output_buffer_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 1;
|
||||
}
|
48
src/Compression/fuzzers/lz4_decompress_fuzzer.cpp
Normal file
48
src/Compression/fuzzers/lz4_decompress_fuzzer.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <Compression/ICompressionCodec.h>
|
||||
#include <IO/BufferWithOwnMemory.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
CompressionCodecPtr getCompressionCodecLZ4(int level);
|
||||
}
|
||||
|
||||
struct AuxiliaryRandomData
|
||||
{
|
||||
size_t level;
|
||||
size_t decompressed_size;
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
|
||||
try
|
||||
{
|
||||
|
||||
if (size < sizeof(AuxiliaryRandomData))
|
||||
return 0;
|
||||
|
||||
auto * p = reinterpret_cast<const AuxiliaryRandomData *>(data);
|
||||
auto codec = DB::getCompressionCodecLZ4(p->level);
|
||||
|
||||
size_t output_buffer_size = p->decompressed_size % 65536;
|
||||
size -= sizeof(AuxiliaryRandomData);
|
||||
data += sizeof(AuxiliaryRandomData) / sizeof(uint8_t);
|
||||
|
||||
std::string input = std::string(reinterpret_cast<const char*>(data), size);
|
||||
fmt::print(stderr, "Using input {} of size {}, output size is {}. \n", input, size, output_buffer_size);
|
||||
|
||||
if (output_buffer_size < size)
|
||||
return 0;
|
||||
|
||||
DB::Memory<> memory;
|
||||
memory.resize(output_buffer_size + codec->getAdditionalSizeAtTheEndOfBuffer());
|
||||
|
||||
codec->doDecompressData(reinterpret_cast<const char *>(data), size, memory.data(), output_buffer_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user