From 1631b5cf3a14969df54c6dd2473085d0ec748388 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 29 May 2020 08:25:43 -0700 Subject: [PATCH] Fixed deflate_quick to not emit a block when there is no available input. Pigz requires no blocks to be emitted in certain instances when calling deflate with Z_BLOCK. Fixed end block not being emitted between calls to deflate_quick causing invalid stored block lengths in certain instances. --- deflate_quick.c | 56 +++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/deflate_quick.c b/deflate_quick.c index 70a7e345..5be963a4 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -26,37 +26,52 @@ extern const ct_data static_ltree[L_CODES+2]; extern const ct_data static_dtree[D_CODES]; +#define QUICK_START_BLOCK(s, last) { \ + zng_tr_emit_tree(s, STATIC_TREES, last); \ + s->block_open = 1; \ + s->block_start = s->strstart; \ +} + +#define QUICK_END_BLOCK(s, last) { \ + if (s->block_open) { \ + zng_tr_emit_end_block(s, static_ltree, last); \ + s->block_open = 0; \ + s->block_start = s->strstart; \ + } \ +} + ZLIB_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { Pos hash_head; unsigned dist, match_len, last; - if (s->block_open == 0) { - last = (flush == Z_FINISH) ? 1 : 0; - zng_tr_emit_tree(s, STATIC_TREES, last); - s->block_open = 1; - } - do { - if (s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size) { - flush_pending(s->strm); - if (s->strm->avail_in == 0 && flush != Z_FINISH) { - return need_more; - } - } - if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - zng_tr_emit_end_block(s, static_ltree, 0); - s->block_open = 0; - s->block_start = s->strstart; - flush_pending(s->strm); + /* Always emit end block, in case next call is with Z_FINISH, + and we need to emit start of last block */ + QUICK_END_BLOCK(s, 0); return need_more; } if (s->lookahead == 0) break; } + if (s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size) { + flush_pending(s->strm); + if (s->strm->avail_out == 0 && flush != Z_FINISH) { + /* Break to emit end block and return need_more */ + break; + } + } + + if (s->block_open == 0) { + /* Start new block when we have lookahead data, so that if no + input data is given an empty block will not be written */ + last = (flush == Z_FINISH) ? 1 : 0; + QUICK_START_BLOCK(s, last); + } + if (s->lookahead >= MIN_MATCH) { hash_head = functable.quick_insert_string(s, s->strstart); dist = s->strstart - hash_head; @@ -83,15 +98,10 @@ ZLIB_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { s->lookahead--; } while (s->strm->avail_out != 0); - if (s->strm->avail_out == 0 && flush != Z_FINISH) - return need_more; - s->insert = s->strstart < MIN_MATCH - 1 ? s->strstart : MIN_MATCH-1; last = (flush == Z_FINISH) ? 1 : 0; - zng_tr_emit_end_block(s, static_ltree, last); - s->block_open = 0; - s->block_start = s->strstart; + QUICK_END_BLOCK(s, last); flush_pending(s->strm); if (last) { -- 2.47.2