From b0f71705955698cf1e0d1101dbe6430566b70b63 Mon Sep 17 00:00:00 2001 From: rocksonhead <30463961+rocksonhead@users.noreply.github.com> Date: Sun, 25 Mar 2018 00:27:03 +0000 Subject: [PATCH] Fix calling multiple ZlibDecompressor in parallel causes adler32 checksum failure (GH #596, #600) --- zinflate.cpp | 60 ++++++++++++++++++++++++++++++---------------------- zinflate.h | 9 ++++---- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/zinflate.cpp b/zinflate.cpp index 9a41462f..4df27c9d 100644 --- a/zinflate.cpp +++ b/zinflate.cpp @@ -612,41 +612,51 @@ void Inflator::FlushOutput() } } -struct NewFixedLiteralDecoder +void Inflator::CreateFixedLiteralDecoder() { - HuffmanDecoder * operator()() const - { - unsigned int codeLengths[288]; - std::fill(codeLengths + 0, codeLengths + 144, 8); - std::fill(codeLengths + 144, codeLengths + 256, 9); - std::fill(codeLengths + 256, codeLengths + 280, 7); - std::fill(codeLengths + 280, codeLengths + 288, 8); - member_ptr pDecoder(new HuffmanDecoder); - pDecoder->Initialize(codeLengths, 288); - return pDecoder.release(); - } + unsigned int codeLengths[288]; + std::fill(codeLengths + 0, codeLengths + 144, 8); + std::fill(codeLengths + 144, codeLengths + 256, 9); + std::fill(codeLengths + 256, codeLengths + 280, 7); + std::fill(codeLengths + 280, codeLengths + 288, 8); + m_fixedLiteralDecoder.reset(new HuffmanDecoder); + m_fixedLiteralDecoder->Initialize(codeLengths, 288); }; -struct NewFixedDistanceDecoder +void Inflator::CreateFixedDistanceDecoder() { - HuffmanDecoder * operator()() const - { - unsigned int codeLengths[32]; - std::fill(codeLengths + 0, codeLengths + 32, 5); - member_ptr pDecoder(new HuffmanDecoder); - pDecoder->Initialize(codeLengths, 32); - return pDecoder.release(); - } + unsigned int codeLengths[32]; + std::fill(codeLengths + 0, codeLengths + 32, 5); + m_fixedDistanceDecoder.reset(new HuffmanDecoder); + m_fixedDistanceDecoder->Initialize(codeLengths, 32); }; -const HuffmanDecoder& Inflator::GetLiteralDecoder() const +const HuffmanDecoder& Inflator::GetLiteralDecoder() { - return m_blockType == 1 ? Singleton().Ref() : m_dynamicLiteralDecoder; + if (m_blockType == 1) + { + if (m_fixedLiteralDecoder.get() == NULLPTR) + CreateFixedLiteralDecoder(); + return *m_fixedLiteralDecoder; + } + else + { + return m_dynamicLiteralDecoder; + } } -const HuffmanDecoder& Inflator::GetDistanceDecoder() const +const HuffmanDecoder& Inflator::GetDistanceDecoder() { - return m_blockType == 1 ? Singleton().Ref() : m_dynamicDistanceDecoder; + if (m_blockType == 1) + { + if (m_fixedDistanceDecoder.get() == NULLPTR) + CreateFixedDistanceDecoder(); + return *m_fixedDistanceDecoder; + } + else + { + return m_dynamicDistanceDecoder; + } } NAMESPACE_END diff --git a/zinflate.h b/zinflate.h index e352aff7..b35071e5 100644 --- a/zinflate.h +++ b/zinflate.h @@ -133,11 +133,11 @@ private: void OutputString(const byte *string, size_t length); void OutputPast(unsigned int length, unsigned int distance); - static const HuffmanDecoder *FixedLiteralDecoder(); - static const HuffmanDecoder *FixedDistanceDecoder(); + void CreateFixedDistanceDecoder(); + void CreateFixedLiteralDecoder(); - const HuffmanDecoder& GetLiteralDecoder() const; - const HuffmanDecoder& GetDistanceDecoder() const; + const HuffmanDecoder& GetLiteralDecoder(); + const HuffmanDecoder& GetDistanceDecoder(); enum State {PRE_STREAM, WAIT_HEADER, DECODING_BODY, POST_STREAM, AFTER_END}; State m_state; @@ -148,6 +148,7 @@ private: NextDecode m_nextDecode; unsigned int m_literal, m_distance; // for LENGTH_BITS or DISTANCE_BITS HuffmanDecoder m_dynamicLiteralDecoder, m_dynamicDistanceDecoder; + member_ptr m_fixedLiteralDecoder, m_fixedDistanceDecoder; LowFirstBitReader m_reader; SecByteBlock m_window; size_t m_current, m_lastFlush;