MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / doDecompressData

Method doDecompressData

src/Compression/CompressionCodecMultiple.cpp:69–132  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

67}
68
69UInt32 CompressionCodecMultiple::doDecompressData(const char * source, UInt32 source_size, char * dest, UInt32 decompressed_size) const
70{
71 if (source_size < 1 || !source[0])
72 throw Exception(decompression_error_code, "Wrong compression methods list");
73
74 UInt8 compression_methods_size = source[0];
75 /// +1 for the compression_methods_size byte itself
76 if (static_cast<UInt32>(compression_methods_size) + 1 > source_size)
77 throw Exception(decompression_error_code, "Wrong compression methods list: header claims {} codecs"
78 " but compressed data is only {} bytes",
79 static_cast<UInt32>(compression_methods_size), source_size);
80
81 PODArray<char> compressed_buf(&source[compression_methods_size + 1], &source[source_size]);
82 PODArray<char> uncompressed_buf;
83 /// Insert all data into compressed buf
84 source_size -= (compression_methods_size + 1);
85
86 for (int idx = compression_methods_size - 1; idx >= 0; --idx)
87 {
88 UInt8 compression_method = source[idx + 1];
89 const auto codec = CompressionCodecFactory::instance().get(compression_method);
90 auto additional_size_at_the_end_of_buffer = codec->getAdditionalSizeAtTheEndOfBuffer();
91
92 if (compressed_buf.size() >= 1_GiB)
93 throw Exception(decompression_error_code, "Too large compressed size: {}", compressed_buf.size());
94
95 if (source_size < COMPRESSED_BLOCK_HEADER_SIZE)
96 throw Exception(decompression_error_code, "Compressed data is too short to contain a block header: {} bytes",
97 source_size);
98
99 {
100 UInt32 bytes_to_resize = 0;
101 if (common::addOverflow(static_cast<UInt32>(compressed_buf.size()), additional_size_at_the_end_of_buffer, bytes_to_resize))
102 throw Exception(decompression_error_code, "Too large compressed size: {}", compressed_buf.size());
103
104 compressed_buf.resize(compressed_buf.size() + additional_size_at_the_end_of_buffer);
105 }
106
107 UInt32 uncompressed_size = readDecompressedBlockSize(compressed_buf.data());
108
109 if (uncompressed_size >= 1_GiB)
110 throw Exception(decompression_error_code, "Too large uncompressed size: {}", uncompressed_size);
111
112 if (idx == 0 && uncompressed_size != decompressed_size)
113 throw Exception(decompression_error_code, "Wrong final decompressed size in codec Multiple, got {}, expected {}",
114 uncompressed_size, decompressed_size);
115
116 {
117 UInt32 bytes_to_resize = 0;
118 if (common::addOverflow(uncompressed_size, additional_size_at_the_end_of_buffer, bytes_to_resize))
119 throw Exception(decompression_error_code, "Too large uncompressed size: {}", uncompressed_size);
120
121 uncompressed_buf.resize(bytes_to_resize);
122 }
123
124 codec->decompress(compressed_buf.data(), source_size, uncompressed_buf.data());
125 uncompressed_buf.swap(compressed_buf);
126 /// The call to decompress will validate uncompressed_size (same readDecompressedBlockSize call as here)

Callers

nothing calls this directly

Calls 10

addOverflowFunction · 0.85
memcpyFunction · 0.85
ExceptionClass · 0.70
getMethod · 0.45
sizeMethod · 0.45
resizeMethod · 0.45
dataMethod · 0.45
decompressMethod · 0.45
swapMethod · 0.45

Tested by

no test coverage detected