]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Fixed deflate_quick to not emit a block when there is no available input. Pigz requir...
authorNathan Moinvaziri <nathan@nathanm.com>
Fri, 29 May 2020 15:25:43 +0000 (08:25 -0700)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Thu, 18 Jun 2020 20:12:10 +0000 (22:12 +0200)
Fixed end block not being emitted between calls to deflate_quick causing invalid stored block lengths in certain instances.

deflate_quick.c

index 70a7e345d16d9d7d66fe27b461cdb6daebd879e8..5be963a445f03c661732b983446005c2ee345584 100644 (file)
 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) {