2626#include " tlAssert.h"
2727
2828#include < algorithm>
29+ #include < cstring>
2930
3031#include < zlib.h>
3132
@@ -227,16 +228,22 @@ InflateFilter::InflateFilter (tl::InputStream &input)
227228 m_last_block (false ),
228229 m_uncompressed_length (0 ) // this forces a new block on "process()"
229230{
230- for (size_t i = 0 ; i < sizeof (m_buffer) / sizeof (m_buffer [0 ]); ++i) {
231- m_buffer[i] = 0 ;
232- }
231+ // NOTE: the minimum buffer size of 65536 corresponds to the maximum block size
232+ // of the block repetition decoder
233+ m_blen = 65536 ; // initially
234+
235+ m_buffer = new char [m_blen];
236+ std::memset (m_buffer, 0 , m_blen);
233237
234238 mp_dist_decoder = new HuffmannDecoder ();
235239 mp_lit_decoder = new HuffmannDecoder ();
236240}
237241
238242InflateFilter::~InflateFilter ()
239243{
244+ delete[] m_buffer;
245+ m_buffer = 0 ;
246+ m_blen = 0 ;
240247 delete mp_dist_decoder;
241248 mp_dist_decoder = 0 ;
242249 delete mp_lit_decoder;
@@ -246,9 +253,36 @@ InflateFilter::~InflateFilter ()
246253const char *
247254InflateFilter::get (size_t n)
248255{
249- tl_assert (n < sizeof (m_buffer) / 2 );
256+ size_t blen = m_blen;
257+ while (n >= blen / 2 ) {
258+ blen *= 2 ;
259+ }
260+
261+ // buffer needs to be enlarged - reallocate
262+ if (blen != m_blen) {
263+
264+ // NOTE: the deflate implementation actually looks back past the read pointer
265+ // (in put_byte_dist), so we have to maintain the bytes between m_b_read
266+ // and m_b_insert too.
267+
268+ char *new_buffer = new char [blen];
269+
270+ // place the current block twice at start and end of the block
271+ std::memcpy (new_buffer, m_buffer, m_blen);
272+ std::memcpy (new_buffer + blen - m_blen, m_buffer, m_blen);
273+
274+ // adjust read pointer if the stored byte array wrapped around the buffer
275+ if (m_b_insert < m_b_read) {
276+ m_b_read += blen - m_blen;
277+ }
278+
279+ delete[] m_buffer;
280+ m_buffer = new_buffer;
281+ m_blen = blen;
282+
283+ }
250284
251- while ((m_b_insert + sizeof (m_buffer) - m_b_read) % sizeof (m_buffer) < n) {
285+ while ((m_b_insert + m_blen - m_b_read) % m_blen < n) {
252286 if (! process ()) {
253287 throw tl::Exception (tl::to_string (tr (" Unexpected end of file (DEFLATE implementation)" )));
254288 }
@@ -257,14 +291,14 @@ InflateFilter::get (size_t n)
257291 tl_assert (m_b_read != m_b_insert);
258292
259293 // ensure the block is accessible as a coherent chunk:
260- if (m_b_read + n >= sizeof (m_buffer) ) {
261- std::rotate (m_buffer, m_buffer + m_b_read, m_buffer + sizeof (m_buffer) );
262- m_b_insert = (m_b_insert - m_b_read + sizeof (m_buffer)) % sizeof (m_buffer) ;
294+ if (m_b_read + n >= m_blen ) {
295+ std::rotate (m_buffer, m_buffer + m_b_read, m_buffer + m_blen );
296+ m_b_insert = (m_b_insert - m_b_read + m_blen) % m_blen ;
263297 m_b_read = 0 ;
264298 }
265299
266300 const char *r = m_buffer + m_b_read;
267- m_b_read = (m_b_read + n) % sizeof (m_buffer) ;
301+ m_b_read = (m_b_read + n) % m_blen ;
268302 return r;
269303}
270304
@@ -290,13 +324,16 @@ void
290324InflateFilter::put_byte (char b)
291325{
292326 m_buffer [m_b_insert] = b;
293- m_b_insert = (m_b_insert + 1 ) % sizeof (m_buffer);
327+ m_b_insert = (m_b_insert + 1 ) % m_blen;
328+ // buffer overrun
329+ tl_assert (m_b_insert != m_b_read);
294330}
295331
296332void
297333InflateFilter::put_byte_dist (unsigned int d)
298334{
299- put_byte (m_buffer [(m_b_insert - d) % sizeof (m_buffer)]);
335+ tl_assert (d < m_blen);
336+ put_byte (m_buffer [(m_b_insert + m_blen - d) % m_blen]);
300337}
301338
302339bool
0 commit comments