Crypto++  5.6.4
Free C++ class library of cryptographic schemes
zinflate.cpp
1 // zinflate.cpp - written and placed in the public domain by Wei Dai
2 
3 // This is a complete reimplementation of the DEFLATE decompression algorithm.
4 // It should not be affected by any security vulnerabilities in the zlib
5 // compression library. In particular it is not affected by the double free bug
6 // (http://www.kb.cert.org/vuls/id/368819).
7 
8 #include "pch.h"
9 
10 #include "zinflate.h"
11 #include "secblock.h"
12 #include "smartptr.h"
13 
14 NAMESPACE_BEGIN(CryptoPP)
15 
17 {
18  inline bool operator()(CryptoPP::HuffmanDecoder::code_t lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs)
19  {return lhs < rhs.code;}
20  // needed for MSVC .NET 2005
21  inline bool operator()(const CryptoPP::HuffmanDecoder::CodeInfo &lhs, const CryptoPP::HuffmanDecoder::CodeInfo &rhs)
22  {return lhs.code < rhs.code;}
23 };
24 
25 inline bool LowFirstBitReader::FillBuffer(unsigned int length)
26 {
27  while (m_bitsBuffered < length)
28  {
29  byte b;
30  if (!m_store.Get(b))
31  return false;
32  m_buffer |= (unsigned long)b << m_bitsBuffered;
33  m_bitsBuffered += 8;
34  }
35  CRYPTOPP_ASSERT(m_bitsBuffered <= sizeof(unsigned long)*8);
36  return true;
37 }
38 
39 inline unsigned long LowFirstBitReader::PeekBits(unsigned int length)
40 {
41  bool result = FillBuffer(length);
42  CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result);
43  return m_buffer & (((unsigned long)1 << length) - 1);
44 }
45 
46 inline void LowFirstBitReader::SkipBits(unsigned int length)
47 {
48  CRYPTOPP_ASSERT(m_bitsBuffered >= length);
49  m_buffer >>= length;
50  m_bitsBuffered -= length;
51 }
52 
53 inline unsigned long LowFirstBitReader::GetBits(unsigned int length)
54 {
55  unsigned long result = PeekBits(length);
56  SkipBits(length);
57  return result;
58 }
59 
60 inline HuffmanDecoder::code_t HuffmanDecoder::NormalizeCode(HuffmanDecoder::code_t code, unsigned int codeBits)
61 {
62  return code << (MAX_CODE_BITS - codeBits);
63 }
64 
65 void HuffmanDecoder::Initialize(const unsigned int *codeBits, unsigned int nCodes)
66 {
67  // the Huffman codes are represented in 3 ways in this code:
68  //
69  // 1. most significant code bit (i.e. top of code tree) in the least significant bit position
70  // 2. most significant code bit (i.e. top of code tree) in the most significant bit position
71  // 3. most significant code bit (i.e. top of code tree) in n-th least significant bit position,
72  // where n is the maximum code length for this code tree
73  //
74  // (1) is the way the codes come in from the deflate stream
75  // (2) is used to sort codes so they can be binary searched
76  // (3) is used in this function to compute codes from code lengths
77  //
78  // a code in representation (2) is called "normalized" here
79  // The BitReverse() function is used to convert between (1) and (2)
80  // The NormalizeCode() function is used to convert from (3) to (2)
81 
82  if (nCodes == 0)
83  throw Err("null code");
84 
85  m_maxCodeBits = *std::max_element(codeBits, codeBits+nCodes);
86 
87  if (m_maxCodeBits > MAX_CODE_BITS)
88  throw Err("code length exceeds maximum");
89 
90  if (m_maxCodeBits == 0)
91  throw Err("null code");
92 
93  // count number of codes of each length
94  SecBlockWithHint<unsigned int, 15+1> blCount(m_maxCodeBits+1);
95  std::fill(blCount.begin(), blCount.end(), 0);
96  unsigned int i;
97  for (i=0; i<nCodes; i++)
98  blCount[codeBits[i]]++;
99 
100  // compute the starting code of each length
101  code_t code = 0;
102  SecBlockWithHint<code_t, 15+1> nextCode(m_maxCodeBits+1);
103  nextCode[1] = 0;
104  for (i=2; i<=m_maxCodeBits; i++)
105  {
106  // compute this while checking for overflow: code = (code + blCount[i-1]) << 1
107  if (code > code + blCount[i-1])
108  throw Err("codes oversubscribed");
109  code += blCount[i-1];
110  if (code > (code << 1))
111  throw Err("codes oversubscribed");
112  code <<= 1;
113  nextCode[i] = code;
114  }
115 
116  // MAX_CODE_BITS is 32, m_maxCodeBits may be smaller.
117  const word64 shiftedMaxCode = ((word64)1 << m_maxCodeBits);
118  if (code > shiftedMaxCode - blCount[m_maxCodeBits])
119  throw Err("codes oversubscribed");
120  else if (m_maxCodeBits != 1 && code < shiftedMaxCode - blCount[m_maxCodeBits])
121  throw Err("codes incomplete");
122 
123  // compute a vector of <code, length, value> triples sorted by code
124  m_codeToValue.resize(nCodes - blCount[0]);
125  unsigned int j=0;
126  for (i=0; i<nCodes; i++)
127  {
128  unsigned int len = codeBits[i];
129  if (len != 0)
130  {
131  code = NormalizeCode(nextCode[len]++, len);
132  m_codeToValue[j].code = code;
133  m_codeToValue[j].len = len;
134  m_codeToValue[j].value = i;
135  j++;
136  }
137  }
138  std::sort(m_codeToValue.begin(), m_codeToValue.end());
139 
140  // initialize the decoding cache
141  m_cacheBits = STDMIN(9U, m_maxCodeBits);
142  m_cacheMask = (1 << m_cacheBits) - 1;
143  m_normalizedCacheMask = NormalizeCode(m_cacheMask, m_cacheBits);
144  CRYPTOPP_ASSERT(m_normalizedCacheMask == BitReverse(m_cacheMask));
145 
146  const word64 shiftedCache = ((word64)1 << m_cacheBits);
147  CRYPTOPP_ASSERT(shiftedCache <= SIZE_MAX);
148  if (m_cache.size() != shiftedCache)
149  m_cache.resize((size_t)shiftedCache);
150 
151  for (i=0; i<m_cache.size(); i++)
152  m_cache[i].type = 0;
153 }
154 
155 void HuffmanDecoder::FillCacheEntry(LookupEntry &entry, code_t normalizedCode) const
156 {
157  normalizedCode &= m_normalizedCacheMask;
158  const CodeInfo &codeInfo = *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode, CodeLessThan())-1);
159  if (codeInfo.len <= m_cacheBits)
160  {
161  entry.type = 1;
162  entry.value = codeInfo.value;
163  entry.len = codeInfo.len;
164  }
165  else
166  {
167  entry.begin = &codeInfo;
168  const CodeInfo *last = & *(std::upper_bound(m_codeToValue.begin(), m_codeToValue.end(), normalizedCode + ~m_normalizedCacheMask, CodeLessThan())-1);
169  if (codeInfo.len == last->len)
170  {
171  entry.type = 2;
172  entry.len = codeInfo.len;
173  }
174  else
175  {
176  entry.type = 3;
177  entry.end = last+1;
178  }
179  }
180 }
181 
182 inline unsigned int HuffmanDecoder::Decode(code_t code, /* out */ value_t &value) const
183 {
184  CRYPTOPP_ASSERT(m_codeToValue.size() > 0);
185  LookupEntry &entry = m_cache[code & m_cacheMask];
186 
187  code_t normalizedCode = 0;
188  if (entry.type != 1)
189  normalizedCode = BitReverse(code);
190 
191  if (entry.type == 0)
192  FillCacheEntry(entry, normalizedCode);
193 
194  if (entry.type == 1)
195  {
196  value = entry.value;
197  return entry.len;
198  }
199  else
200  {
201  const CodeInfo &codeInfo = (entry.type == 2)
202  ? entry.begin[(normalizedCode << m_cacheBits) >> (MAX_CODE_BITS - (entry.len - m_cacheBits))]
203  : *(std::upper_bound(entry.begin, entry.end, normalizedCode, CodeLessThan())-1);
204  value = codeInfo.value;
205  return codeInfo.len;
206  }
207 }
208 
209 bool HuffmanDecoder::Decode(LowFirstBitReader &reader, value_t &value) const
210 {
211  bool result = reader.FillBuffer(m_maxCodeBits);
212  CRYPTOPP_UNUSED(result); // CRYPTOPP_ASSERT(result);
213 
214  unsigned int codeBits = Decode(reader.PeekBuffer(), value);
215  if (codeBits > reader.BitsBuffered())
216  return false;
217  reader.SkipBits(codeBits);
218  return true;
219 }
220 
221 // *************************************************************
222 
223 Inflator::Inflator(BufferedTransformation *attachment, bool repeat, int propagation)
224  : AutoSignaling<Filter>(propagation)
225  , m_state(PRE_STREAM), m_repeat(repeat), m_eof(0), m_wrappedAround(0)
226  , m_blockType(0xff), m_storedLen(0xffff), m_nextDecode(), m_literal(0)
227  , m_distance(0), m_reader(m_inQueue), m_current(0), m_lastFlush(0)
228 {
229  Detach(attachment);
230 }
231 
233 {
234  m_state = PRE_STREAM;
235  parameters.GetValue("Repeat", m_repeat);
236  m_inQueue.Clear();
237  m_reader.SkipBits(m_reader.BitsBuffered());
238 }
239 
240 void Inflator::OutputByte(byte b)
241 {
242  m_window[m_current++] = b;
243  if (m_current == m_window.size())
244  {
245  ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush);
246  m_lastFlush = 0;
247  m_current = 0;
248  m_wrappedAround = true;
249  }
250 }
251 
252 void Inflator::OutputString(const byte *string, size_t length)
253 {
254  while (length)
255  {
256  size_t len = UnsignedMin(length, m_window.size() - m_current);
257  memcpy(m_window + m_current, string, len);
258  m_current += len;
259  if (m_current == m_window.size())
260  {
261  ProcessDecompressedData(m_window + m_lastFlush, m_window.size() - m_lastFlush);
262  m_lastFlush = 0;
263  m_current = 0;
264  m_wrappedAround = true;
265  }
266  string += len;
267  length -= len;
268  }
269 }
270 
271 void Inflator::OutputPast(unsigned int length, unsigned int distance)
272 {
273  size_t start;
274  if (distance <= m_current)
275  start = m_current - distance;
276  else if (m_wrappedAround && distance <= m_window.size())
277  start = m_current + m_window.size() - distance;
278  else
279  throw BadBlockErr();
280 
281  if (start + length > m_window.size())
282  {
283  for (; start < m_window.size(); start++, length--)
284  OutputByte(m_window[start]);
285  start = 0;
286  }
287 
288  if (start + length > m_current || m_current + length >= m_window.size())
289  {
290  while (length--)
291  OutputByte(m_window[start++]);
292  }
293  else
294  {
295  memcpy(m_window + m_current, m_window + start, length);
296  m_current += length;
297  }
298 }
299 
300 size_t Inflator::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
301 {
302  if (!blocking)
303  throw BlockingInputOnly("Inflator");
304 
305  LazyPutter lp(m_inQueue, inString, length);
306  ProcessInput(messageEnd != 0);
307 
308  if (messageEnd)
309  if (!(m_state == PRE_STREAM || m_state == AFTER_END))
310  throw UnexpectedEndErr();
311 
312  Output(0, NULL, 0, messageEnd, blocking);
313  return 0;
314 }
315 
316 bool Inflator::IsolatedFlush(bool hardFlush, bool blocking)
317 {
318  if (!blocking)
319  throw BlockingInputOnly("Inflator");
320 
321  if (hardFlush)
322  ProcessInput(true);
323  FlushOutput();
324 
325  return false;
326 }
327 
328 void Inflator::ProcessInput(bool flush)
329 {
330  while (true)
331  {
332  switch (m_state)
333  {
334  case PRE_STREAM:
335  if (!flush && m_inQueue.CurrentSize() < MaxPrestreamHeaderSize())
336  return;
337  ProcessPrestreamHeader();
338  m_state = WAIT_HEADER;
339  m_wrappedAround = false;
340  m_current = 0;
341  m_lastFlush = 0;
342  m_window.New(((size_t) 1) << GetLog2WindowSize());
343  break;
344  case WAIT_HEADER:
345  {
346  // maximum number of bytes before actual compressed data starts
347  const size_t MAX_HEADER_SIZE = BitsToBytes(3+5+5+4+19*7+286*15+19*15);
348  if (m_inQueue.CurrentSize() < (flush ? 1 : MAX_HEADER_SIZE))
349  return;
350  DecodeHeader();
351  break;
352  }
353  case DECODING_BODY:
354  if (!DecodeBody())
355  return;
356  break;
357  case POST_STREAM:
358  if (!flush && m_inQueue.CurrentSize() < MaxPoststreamTailSize())
359  return;
360  ProcessPoststreamTail();
361  m_state = m_repeat ? PRE_STREAM : AFTER_END;
362  Output(0, NULL, 0, GetAutoSignalPropagation(), true); // TODO: non-blocking
363  if (m_inQueue.IsEmpty())
364  return;
365  break;
366  case AFTER_END:
367  m_inQueue.TransferTo(*AttachedTransformation());
368  return;
369  }
370  }
371 }
372 
373 void Inflator::DecodeHeader()
374 {
375  if (!m_reader.FillBuffer(3))
376  throw UnexpectedEndErr();
377  m_eof = m_reader.GetBits(1) != 0;
378  m_blockType = (byte)m_reader.GetBits(2);
379  switch (m_blockType)
380  {
381  case 0: // stored
382  {
383  m_reader.SkipBits(m_reader.BitsBuffered() % 8);
384  if (!m_reader.FillBuffer(32))
385  throw UnexpectedEndErr();
386  m_storedLen = (word16)m_reader.GetBits(16);
387  word16 nlen = (word16)m_reader.GetBits(16);
388  if (nlen != (word16)~m_storedLen)
389  throw BadBlockErr();
390  break;
391  }
392  case 1: // fixed codes
393  m_nextDecode = LITERAL;
394  break;
395  case 2: // dynamic codes
396  {
397  if (!m_reader.FillBuffer(5+5+4))
398  throw UnexpectedEndErr();
399  unsigned int hlit = m_reader.GetBits(5);
400  unsigned int hdist = m_reader.GetBits(5);
401  unsigned int hclen = m_reader.GetBits(4);
402 
404  unsigned int i;
405  static const unsigned int border[] = { // Order of the bit length code lengths
406  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
407  std::fill(codeLengths.begin(), codeLengths+19, 0);
408  for (i=0; i<hclen+4; i++)
409  codeLengths[border[i]] = m_reader.GetBits(3);
410 
411  try
412  {
413  HuffmanDecoder codeLengthDecoder(codeLengths, 19);
414  for (i = 0; i < hlit+257+hdist+1; )
415  {
416  unsigned int k = 0, count = 0, repeater = 0;
417  bool result = codeLengthDecoder.Decode(m_reader, k);
418  if (!result)
419  throw UnexpectedEndErr();
420  if (k <= 15)
421  {
422  count = 1;
423  repeater = k;
424  }
425  else switch (k)
426  {
427  case 16:
428  if (!m_reader.FillBuffer(2))
429  throw UnexpectedEndErr();
430  count = 3 + m_reader.GetBits(2);
431  if (i == 0)
432  throw BadBlockErr();
433  repeater = codeLengths[i-1];
434  break;
435  case 17:
436  if (!m_reader.FillBuffer(3))
437  throw UnexpectedEndErr();
438  count = 3 + m_reader.GetBits(3);
439  repeater = 0;
440  break;
441  case 18:
442  if (!m_reader.FillBuffer(7))
443  throw UnexpectedEndErr();
444  count = 11 + m_reader.GetBits(7);
445  repeater = 0;
446  break;
447  }
448  if (i + count > hlit+257+hdist+1)
449  throw BadBlockErr();
450  std::fill(codeLengths + i, codeLengths + i + count, repeater);
451  i += count;
452  }
453  m_dynamicLiteralDecoder.Initialize(codeLengths, hlit+257);
454  if (hdist == 0 && codeLengths[hlit+257] == 0)
455  {
456  if (hlit != 0) // a single zero distance code length means all literals
457  throw BadBlockErr();
458  }
459  else
460  m_dynamicDistanceDecoder.Initialize(codeLengths+hlit+257, hdist+1);
461  m_nextDecode = LITERAL;
462  }
463  catch (HuffmanDecoder::Err &)
464  {
465  throw BadBlockErr();
466  }
467  break;
468  }
469  default:
470  throw BadBlockErr(); // reserved block type
471  }
472  m_state = DECODING_BODY;
473 }
474 
475 bool Inflator::DecodeBody()
476 {
477  bool blockEnd = false;
478  switch (m_blockType)
479  {
480  case 0: // stored
481  CRYPTOPP_ASSERT(m_reader.BitsBuffered() == 0);
482  while (!m_inQueue.IsEmpty() && !blockEnd)
483  {
484  size_t size;
485  const byte *block = m_inQueue.Spy(size);
486  size = UnsignedMin(m_storedLen, size);
487  CRYPTOPP_ASSERT(size <= 0xffff);
488 
489  OutputString(block, size);
490  m_inQueue.Skip(size);
491  m_storedLen = m_storedLen - (word16)size;
492  if (m_storedLen == 0)
493  blockEnd = true;
494  }
495  break;
496  case 1: // fixed codes
497  case 2: // dynamic codes
498  static const unsigned int lengthStarts[] = {
499  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
500  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
501  static const unsigned int lengthExtraBits[] = {
502  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
503  3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
504  static const unsigned int distanceStarts[] = {
505  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
506  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
507  8193, 12289, 16385, 24577};
508  static const unsigned int distanceExtraBits[] = {
509  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
510  7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
511  12, 12, 13, 13};
512 
513  const HuffmanDecoder& literalDecoder = GetLiteralDecoder();
514  const HuffmanDecoder& distanceDecoder = GetDistanceDecoder();
515 
516  switch (m_nextDecode)
517  {
518  case LITERAL:
519  while (true)
520  {
521  if (!literalDecoder.Decode(m_reader, m_literal))
522  {
523  m_nextDecode = LITERAL;
524  break;
525  }
526  if (m_literal < 256)
527  OutputByte((byte)m_literal);
528  else if (m_literal == 256) // end of block
529  {
530  blockEnd = true;
531  break;
532  }
533  else
534  {
535  if (m_literal > 285)
536  throw BadBlockErr();
537  unsigned int bits;
538  case LENGTH_BITS:
539  bits = lengthExtraBits[m_literal-257];
540  if (!m_reader.FillBuffer(bits))
541  {
542  m_nextDecode = LENGTH_BITS;
543  break;
544  }
545  m_literal = m_reader.GetBits(bits) + lengthStarts[m_literal-257];
546  case DISTANCE:
547  if (!distanceDecoder.Decode(m_reader, m_distance))
548  {
549  m_nextDecode = DISTANCE;
550  break;
551  }
552  case DISTANCE_BITS:
553  bits = distanceExtraBits[m_distance];
554  if (!m_reader.FillBuffer(bits))
555  {
556  m_nextDecode = DISTANCE_BITS;
557  break;
558  }
559  m_distance = m_reader.GetBits(bits) + distanceStarts[m_distance];
560  OutputPast(m_literal, m_distance);
561  }
562  }
563  break;
564  default:
565  CRYPTOPP_ASSERT(0);
566  }
567  }
568  if (blockEnd)
569  {
570  if (m_eof)
571  {
572  FlushOutput();
573  m_reader.SkipBits(m_reader.BitsBuffered()%8);
574  if (m_reader.BitsBuffered())
575  {
576  // undo too much lookahead
577  SecBlockWithHint<byte, 4> buffer(m_reader.BitsBuffered() / 8);
578  for (unsigned int i=0; i<buffer.size(); i++)
579  buffer[i] = (byte)m_reader.GetBits(8);
580  m_inQueue.Unget(buffer, buffer.size());
581  }
582  m_state = POST_STREAM;
583  }
584  else
585  m_state = WAIT_HEADER;
586  }
587  return blockEnd;
588 }
589 
590 void Inflator::FlushOutput()
591 {
592  if (m_state != PRE_STREAM)
593  {
594  CRYPTOPP_ASSERT(m_current >= m_lastFlush);
595  ProcessDecompressedData(m_window + m_lastFlush, m_current - m_lastFlush);
596  m_lastFlush = m_current;
597  }
598 }
599 
601 {
602  HuffmanDecoder * operator()() const
603  {
604  unsigned int codeLengths[288];
605  std::fill(codeLengths + 0, codeLengths + 144, 8);
606  std::fill(codeLengths + 144, codeLengths + 256, 9);
607  std::fill(codeLengths + 256, codeLengths + 280, 7);
608  std::fill(codeLengths + 280, codeLengths + 288, 8);
610  pDecoder->Initialize(codeLengths, 288);
611  return pDecoder.release();
612  }
613 };
614 
616 {
617  HuffmanDecoder * operator()() const
618  {
619  unsigned int codeLengths[32];
620  std::fill(codeLengths + 0, codeLengths + 32, 5);
622  pDecoder->Initialize(codeLengths, 32);
623  return pDecoder.release();
624  }
625 };
626 
627 const HuffmanDecoder& Inflator::GetLiteralDecoder() const
628 {
629  return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedLiteralDecoder>().Ref() : m_dynamicLiteralDecoder;
630 }
631 
632 const HuffmanDecoder& Inflator::GetDistanceDecoder() const
633 {
634  return m_blockType == 1 ? Singleton<HuffmanDecoder, NewFixedDistanceDecoder>().Ref() : m_dynamicDistanceDecoder;
635 }
636 
637 NAMESPACE_END
Inflator(BufferedTransformation *attachment=NULL, bool repeat=false, int autoSignalPropagation=-1)
RFC 1951 Decompressor.
Definition: zinflate.cpp:223
use this to make sure LazyPut is finalized in event of exception
Definition: queue.h:129
Stack-based SecBlock that grows into the heap.
Definition: secblock.h:776
Restricts the instantiation of a class to one static object without locks.
Definition: misc.h:264
size_t BitsToBytes(size_t bitCount)
Returns the number of 8-bit bytes or octets required for the specified number of bits.
Definition: misc.h:740
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
Classes for automatic resource management.
bool IsolatedFlush(bool hardFlush, bool blocking)
Flushes data buffered by this object, without signal propagation.
Definition: zinflate.cpp:316
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:647
Interface for buffered transformations.
Definition: cryptlib.h:1359
byte BitReverse(byte value)
Reverses bits in a 8-bit value.
Definition: misc.h:1784
Pointer that overloads operator ->
Definition: smartptr.h:39
Classes and functions for secure memory allocations.
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
Definition: zinflate.cpp:232
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:340
lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
move transferMax bytes of the buffered output to target as input
Definition: cryptlib.h:1663
void Detach(BufferedTransformation *newAttachment=NULL)
Replace an attached transformation.
Definition: filters.cpp:50
BufferedTransformation * AttachedTransformation()
Retrieve attached transformation.
Definition: filters.cpp:36
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:503
virtual lword Skip(lword skipMax=LWORD_MAX)
Discard skipMax bytes from the output buffer.
Definition: cryptlib.cpp:553
Huffman Decoder.
Definition: zinflate.h:33
Fixed size stack-based SecBlock.
Definition: secblock.h:753
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:467
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:62
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:499
Exception thrown by objects that have not implemented nonblocking input processing.
Definition: cryptlib.h:1479
Provides auto signaling support.
Definition: simple.h:226
Implementation of BufferedTransformation's attachment interface.
Definition: filters.h:36
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
Definition: zinflate.cpp:300
BufferedTransformation & Ref()
Provides a reference to this object.
Definition: cryptlib.h:1375
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:515
Crypto++ library namespace.
#define SIZE_MAX
The maximum value of a machine word.
Definition: misc.h:95
Interface for retrieving values given their names.
Definition: cryptlib.h:282