diff --git a/src/protocol/CompressionHandler.cpp b/src/protocol/CompressionHandler.cpp index 0b1f900..321296a 100644 --- a/src/protocol/CompressionHandler.cpp +++ b/src/protocol/CompressionHandler.cpp @@ -1,4 +1,3 @@ -#include #include #include "CompressionHandler.h" #define QLZ_COMPRESSION_LEVEL 1 @@ -39,17 +38,38 @@ namespace ts::compression { void* buffer_ptr{nullptr}; size_t buffer_length{0}; }; + + class qlz_states { + public: + qlz_states() noexcept { + this->state_compress = (qlz_state_compress*) malloc(sizeof(qlz_state_compress)); + this->state_decompress = (qlz_state_decompress*) malloc(sizeof(qlz_state_decompress)); + } + + ~qlz_states() { + ::free(this->state_compress); + ::free(this->state_decompress); + } + + qlz_state_compress* state_compress{nullptr}; + qlz_state_decompress* state_decompress{nullptr}; + private: + }; + thread_local thread_buffer qlz_buffer{}; + thread_local qlz_states qlz_states{}; size_t qlz_decompressed_size(const void* payload, size_t payload_length) { + if(payload_length < 9) return 0; /* payload too small */ + return qlz_size_decompressed((char*) payload) + 400; } bool qlz_decompress_payload(const void* payload, void* buffer, size_t* buffer_size) { + if(!qlz_states.state_decompress) return false; assert(payload != buffer); - qlz_state_decompress state{}; - size_t data_length = qlz_decompress((char*) payload, (char*) buffer, &state); + size_t data_length = qlz_decompress((char*) payload, (char*) buffer, qlz_states.state_decompress); if(data_length <= 0) return false; @@ -60,16 +80,18 @@ namespace ts::compression { } size_t qlz_compressed_size(const void* payload, size_t payload_length) { + assert(payload_length >= 9); //// "Always allocate size + 400 bytes for the destination buffer when compressing." <= http://www.quicklz.com/manual.html return max(min(payload_length * 2, (size_t) (payload_length + 400ULL)), (size_t) 24ULL); /* at least 12 bytes (QLZ header) */ } bool qlz_compress_payload(const void* payload, size_t payload_length, void* buffer, size_t* buffer_length) { + if(!qlz_states.state_compress) return false; + assert(payload != buffer); assert(*buffer_length >= qlz_compressed_size(payload, payload_length)); - qlz_state_compress state{}; - size_t compressed_length = qlz_compress(payload, (char*) buffer, payload_length, &state); + size_t compressed_length = qlz_compress(payload, (char*) buffer, payload_length, qlz_states.state_compress); if(compressed_length > *buffer_length) terminate(); if(compressed_length <= 0) @@ -99,6 +121,9 @@ bool CompressionHandler::decompress(protocol::BasicPacket* packet, std::string & if(expected_length > this->max_packet_size){ //Max 16MB. (97% Compression!) error = "Invalid packet size. (Calculated target length of " + to_string(expected_length) + ". Max length: " + to_string(this->max_packet_size) + ")"; return false; + } else if(expected_length == 0) { + error = "Failed to calculate decompressed packet length"; + return false; } auto header_length = packet->header().length() + packet->mac().length(); auto buffer = buffer::allocate_buffer(expected_length + header_length); diff --git a/src/protocol/CompressionHandler.h b/src/protocol/CompressionHandler.h index b76d655..cd8c541 100644 --- a/src/protocol/CompressionHandler.h +++ b/src/protocol/CompressionHandler.h @@ -4,6 +4,7 @@ namespace ts { namespace compression { + /* Attention: These methods does not validate the data! */ size_t qlz_decompressed_size(const void* payload, size_t payload_length); bool qlz_decompress_payload(const void* payload, void* buffer, size_t* buffer_size); //Attention: payload & buffer must be differen! diff --git a/test/SQL2Test.cpp b/test/SQL2Test.cpp index e7285a4..55fdd42 100644 --- a/test/SQL2Test.cpp +++ b/test/SQL2Test.cpp @@ -7,6 +7,7 @@ #include #include +#if 0 template struct Column { constexpr explicit Column(const std::string_view& name) : name{name} { } @@ -166,4 +167,23 @@ int main() { std::string value{}; insert.add_entry(2, value); insert.execute(nullptr); +} +#endif + +struct A { + A() {} + ~A() = default; +}; + +#include +int main() { + std::set elements{}; + if(!elements.empty()) { + auto it = elements.begin(); + const int* last_element{&*(it++)}; /* if elements would be empty this would be undefined behaviour */ + while(it != elements.end()) { + const auto now = *it++; + const auto diff = last_element - now; + } + } } \ No newline at end of file