diff options
author | Tianjie Xu <xunchang@google.com> | 2017-11-17 16:06:30 -0800 |
---|---|---|
committer | Tianjie Xu <xunchang@google.com> | 2017-11-17 16:54:05 -0800 |
commit | d4875cd3207eb21a992796b23151546e5bd4bf5c (patch) | |
tree | ec48cc852bd6266ae6c29fc855df3aab4ec09b27 | |
parent | 2ab0083e1eae29dfb27f1cf005a4a1c26e5612f9 (diff) | |
download | bsdiff-d4875cd3207eb21a992796b23151546e5bd4bf5c.tar.gz |
Fix the bspatch failure on an empty brotli stream
When we close the BrotliDecompressor, we check for
BrotliDecoderIsFinished(). This function may return false if we never
call BrotliDecoderDecompressStream(), leading to a failure in bspatch
in case of an empty brotli stream.
This CL fixes the issue by checking BrotliDecoderIsUsed() along with
IsFinished(). Since we have the compressed stream and the precomputed
uncompressed size in the patch; we need these checks to avoid unexpected
size mismatch.
Bug: 69472150
Test: unittest pass
Change-Id: Icf7b324836fa59fd3111ba91b03622215a0c8f5f
-rw-r--r-- | brotli_compressor_unittest.cc | 15 | ||||
-rw-r--r-- | brotli_decompressor.cc | 7 | ||||
-rw-r--r-- | patch_reader_unittest.cc | 5 |
3 files changed, 23 insertions, 4 deletions
diff --git a/brotli_compressor_unittest.cc b/brotli_compressor_unittest.cc index 079b985..38492e4 100644 --- a/brotli_compressor_unittest.cc +++ b/brotli_compressor_unittest.cc @@ -37,4 +37,19 @@ TEST(BrotliCompressorTest, BrotliCompressorSmoke) { decompressed_data); } +TEST(BrotliCompressorTest, BrotliCompressorEmptyStream) { + uint8_t empty_buffer[] = {}; + BrotliCompressor brotli_compressor; + EXPECT_TRUE(brotli_compressor.Write(empty_buffer, sizeof(empty_buffer))); + EXPECT_TRUE(brotli_compressor.Finish()); + + std::vector<uint8_t> compressed_data = brotli_compressor.GetCompressedData(); + + // Check that we can close the decompressor without errors. + BrotliDecompressor brotli_decompressor; + EXPECT_TRUE(brotli_decompressor.SetInputData(compressed_data.data(), + compressed_data.size())); + EXPECT_TRUE(brotli_decompressor.Close()); +} + } // namespace bsdiff
\ No newline at end of file diff --git a/brotli_decompressor.cc b/brotli_decompressor.cc index 683e391..f173a75 100644 --- a/brotli_decompressor.cc +++ b/brotli_decompressor.cc @@ -49,7 +49,12 @@ bool BrotliDecompressor::Read(uint8_t* output_data, size_t bytes_to_output) { } bool BrotliDecompressor::Close() { - if (!BrotliDecoderIsFinished(brotli_decoder_state_)) { + // In some cases, the brotli compressed stream could be empty. As a result, + // the function BrotliDecoderIsFinished() will return false because we never + // start the decompression. When that happens, we just destroy the decoder + // and return true. + if (BrotliDecoderIsUsed(brotli_decoder_state_) && + !BrotliDecoderIsFinished(brotli_decoder_state_)) { LOG(ERROR) << "Unfinished brotli decoder." << endl; return false; } diff --git a/patch_reader_unittest.cc b/patch_reader_unittest.cc index 61b63b7..7fe3650 100644 --- a/patch_reader_unittest.cc +++ b/patch_reader_unittest.cc @@ -72,7 +72,6 @@ class PatchReaderTest : public testing::Test { std::back_inserter(*patch_data)); } - void VerifyPatch(const std::vector<uint8_t>& patch_data) { BsdiffPatchReader patch_reader; EXPECT_TRUE(patch_reader.Init(patch_data.data(), patch_data.size())); @@ -108,7 +107,7 @@ class PatchReaderTest : public testing::Test { std::unique_ptr<CompressorInterface> extra_stream_{nullptr}; }; -TEST_F(PatchReaderTest, BZ2PatchReaderLegacyFormatSmoke) { +TEST_F(PatchReaderTest, PatchReaderLegacyFormatSmoke) { ctrl_stream_.reset(new BZ2Compressor()); diff_stream_.reset(new BZ2Compressor()); extra_stream_.reset(new BZ2Compressor()); @@ -123,7 +122,7 @@ TEST_F(PatchReaderTest, BZ2PatchReaderLegacyFormatSmoke) { VerifyPatch(patch_data); } -TEST_F(PatchReaderTest, BZ2PatchReaderNewFormatSmoke) { +TEST_F(PatchReaderTest, PatchReaderNewFormatSmoke) { // Compress the data with one bz2 and two brotli compressors. ctrl_stream_.reset(new BZ2Compressor()); diff_stream_.reset(new BrotliCompressor()); |