Fix corruption error when compressing blob data with zlib. (#9572)

Summary:
The plain data length may not be big enough if the compression actually expands data. So use deflateBound() to get the upper limit on the compressed output before deflate().

Pull Request resolved: https://github.com/facebook/rocksdb/pull/9572

Reviewed By: riversand963

Differential Revision: D34326475

Pulled By: ajkr

fbshipit-source-id: 4b679cb7a83a62782a127785b4d5eb9aa4646449
This commit is contained in:
jingkai.yuan 2022-03-02 16:35:21 -08:00 committed by Andrew Kryczka
parent 39af4e9565
commit 82f1c1418b

View File

@ -724,9 +724,6 @@ inline bool Zlib_Compress(const CompressionInfo& info,
output_header_len = compression::PutDecompressedSizeInfo( output_header_len = compression::PutDecompressedSizeInfo(
output, static_cast<uint32_t>(length)); output, static_cast<uint32_t>(length));
} }
// Resize output to be the plain data length.
// This may not be big enough if the compression actually expands data.
output->resize(output_header_len + length);
// The memLevel parameter specifies how much memory should be allocated for // The memLevel parameter specifies how much memory should be allocated for
// the internal compression state. // the internal compression state.
@ -760,12 +757,16 @@ inline bool Zlib_Compress(const CompressionInfo& info,
} }
} }
// Get an upper bound on the compressed size.
size_t upper_bound = deflateBound(&_stream, length);
output->resize(output_header_len + upper_bound);
// Compress the input, and put compressed data in output. // Compress the input, and put compressed data in output.
_stream.next_in = (Bytef*)input; _stream.next_in = (Bytef*)input;
_stream.avail_in = static_cast<unsigned int>(length); _stream.avail_in = static_cast<unsigned int>(length);
// Initialize the output size. // Initialize the output size.
_stream.avail_out = static_cast<unsigned int>(length); _stream.avail_out = static_cast<unsigned int>(upper_bound);
_stream.next_out = reinterpret_cast<Bytef*>(&(*output)[output_header_len]); _stream.next_out = reinterpret_cast<Bytef*>(&(*output)[output_header_len]);
bool compressed = false; bool compressed = false;