summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTianjie Xu <xunchang@google.com>2017-11-17 16:06:30 -0800
committerTianjie Xu <xunchang@google.com>2017-11-17 16:54:05 -0800
commitd4875cd3207eb21a992796b23151546e5bd4bf5c (patch)
treeec48cc852bd6266ae6c29fc855df3aab4ec09b27
parent2ab0083e1eae29dfb27f1cf005a4a1c26e5612f9 (diff)
downloadbsdiff-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.cc15
-rw-r--r--brotli_decompressor.cc7
-rw-r--r--patch_reader_unittest.cc5
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());