diff --git a/zinflate.cpp b/zinflate.cpp index d9b36c0e1..86a09c45a 100644 --- a/zinflate.cpp +++ b/zinflate.cpp @@ -403,7 +403,17 @@ void Inflator::DecodeHeader() unsigned int hclen = m_reader.GetBits(4); unsigned int i = 0; + // RFC 1951 allows HLIT values 0 to 29, encoding 257 to 286 literal/length + // codes. Values 30 and 31 are invalid and can overrun codeLengths below. + if (hlit > 29) + throw BadBlockErr(); + + const unsigned int literalCount = hlit + 257; + const unsigned int distanceCount = hdist + 1; + const unsigned int codeLengthCount = literalCount + distanceCount; + FixedSizeSecBlock codeLengths; + CRYPTOPP_ASSERT(codeLengthCount <= codeLengths.size()); static const unsigned int border[] = { // Order of the bit length code lengths 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; std::fill(codeLengths.begin(), codeLengths+19, 0); @@ -418,7 +428,7 @@ void Inflator::DecodeHeader() bool result = false; unsigned int k=0, count=0, repeater=0; HuffmanDecoder codeLengthDecoder(codeLengths, 19); - for (i=0; i < hlit+257+hdist+1; ) + for (i=0; i < codeLengthCount; ) { k = 0, count = 0, repeater = 0; result = codeLengthDecoder.Decode(m_reader, k); @@ -452,19 +462,21 @@ void Inflator::DecodeHeader() repeater = 0; break; } - if (i + count > hlit+257+hdist+1) + if (count > codeLengthCount - i || + i > codeLengths.size() || + count > codeLengths.size() - i) throw BadBlockErr(); std::fill(codeLengths + i, codeLengths + i + count, repeater); i += count; } - m_dynamicLiteralDecoder.Initialize(codeLengths, hlit+257); - if (hdist == 0 && codeLengths[hlit+257] == 0) + m_dynamicLiteralDecoder.Initialize(codeLengths, literalCount); + if (hdist == 0 && codeLengths[literalCount] == 0) { if (hlit != 0) // a single zero distance code length means all literals throw BadBlockErr(); } else - m_dynamicDistanceDecoder.Initialize(codeLengths+hlit+257, hdist+1); + m_dynamicDistanceDecoder.Initialize(codeLengths+literalCount, distanceCount); m_nextDecode = LITERAL; } catch (HuffmanDecoder::Err &)