Index: third_party/protobuf/src/google/protobuf/io/gzip_stream.cc |
diff --git a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc |
index 84d277f48377939edb0f71f06e1339b90d6bf0f6..0f1ff872aa419a980fdd5813840552c12d96561b 100644 |
--- a/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc |
+++ b/third_party/protobuf/src/google/protobuf/io/gzip_stream.cc |
@@ -73,6 +73,17 @@ GzipInputStream::~GzipInputStream() { |
zerror_ = inflateEnd(&zcontext_); |
} |
+static inline int internalInflateInit2( |
+ z_stream* zcontext, GzipInputStream::Format format) { |
+ int windowBitsFormat = 0; |
+ switch (format) { |
+ case GzipInputStream::GZIP: windowBitsFormat = 16; break; |
+ case GzipInputStream::AUTO: windowBitsFormat = 32; break; |
+ case GzipInputStream::ZLIB: windowBitsFormat = 0; break; |
+ } |
+ return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat); |
+} |
+ |
int GzipInputStream::Inflate(int flush) { |
if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) { |
// previous inflate filled output buffer. don't change input params yet. |
@@ -89,14 +100,7 @@ int GzipInputStream::Inflate(int flush) { |
zcontext_.next_in = static_cast<Bytef*>(const_cast<void*>(in)); |
zcontext_.avail_in = in_size; |
if (first) { |
- int windowBitsFormat = 0; |
- switch (format_) { |
- case GZIP: windowBitsFormat = 16; break; |
- case AUTO: windowBitsFormat = 32; break; |
- case ZLIB: windowBitsFormat = 0; break; |
- } |
- int error = inflateInit2(&zcontext_, |
- /* windowBits */15 | windowBitsFormat); |
+ int error = internalInflateInit2(&zcontext_, format_); |
if (error != Z_OK) { |
return error; |
} |
@@ -127,9 +131,21 @@ bool GzipInputStream::Next(const void** data, int* size) { |
return true; |
} |
if (zerror_ == Z_STREAM_END) { |
- *data = NULL; |
- *size = 0; |
- return false; |
+ if (zcontext_.next_out != NULL) { |
+ // sub_stream_ may have concatenated streams to follow |
+ zerror_ = inflateEnd(&zcontext_); |
+ if (zerror_ != Z_OK) { |
+ return false; |
+ } |
+ zerror_ = internalInflateInit2(&zcontext_, format_); |
+ if (zerror_ != Z_OK) { |
+ return false; |
+ } |
+ } else { |
+ *data = NULL; |
+ *size = 0; |
+ return false; |
+ } |
} |
zerror_ = Inflate(Z_NO_FLUSH); |
if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) { |
@@ -251,8 +267,7 @@ int GzipOutputStream::Deflate(int flush) { |
} |
error = deflate(&zcontext_, flush); |
} while (error == Z_OK && zcontext_.avail_out == 0); |
- if (((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) |
- && (zcontext_.avail_out != sub_data_size_)) { |
+ if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { |
// Notify lower layer of data. |
sub_stream_->BackUp(zcontext_.avail_out); |
// We don't own the buffer anymore. |