Make the Deflate decoder correctly handle the special case of a
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 1 Jun 2012 19:37:14 +0000 (19:37 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Fri, 1 Jun 2012 19:37:14 +0000 (19:37 +0000)
dynamic block in which the backward-distances Huffman table contains
no entries at all. (In this situation it's impossible to use the
distance table, and therefore the block must contain nothing but
Huffman-coded literals.)

git-svn-id: svn://svn.tartarus.org/sgt/halibut@9550 cda61777-01e9-0310-a592-d414129be87e

deflate.c
deflate.h

index d614c37..186e14c 100644 (file)
--- a/deflate.c
+++ b/deflate.c
@@ -2297,14 +2297,25 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
                                             &error);
                if (!dctx->currlentable)
                    goto finished;     /* error code set up by mktable */
                                             &error);
                if (!dctx->currlentable)
                    goto finished;     /* error code set up by mktable */
-               dctx->currdisttable = mktable(dctx->lengths + dctx->hlit,
-                                             dctx->hdist,
+                if (dctx->hdist == 1 && dctx->lengths[dctx->hlit] == 0) {
+                    /*
+                     * Special case: if the code length list for the
+                     * backward-distance table contains a single zero
+                     * entry, it means this block will never encode a
+                     * backward distance at all (i.e. it's all
+                     * literals).
+                     */
+                    dctx->currdisttable = NULL;
+                } else {
+                    dctx->currdisttable = mktable(dctx->lengths + dctx->hlit,
+                                                  dctx->hdist,
 #ifdef ANALYSIS
 #ifdef ANALYSIS
-                                             "distance",
+                                                  "distance",
 #endif
 #endif
-                                             &error);
-               if (!dctx->currdisttable)
-                   goto finished;     /* error code set up by mktable */
+                                                  &error);
+                    if (!dctx->currdisttable)
+                        goto finished;     /* error code set up by mktable */
+                }
                freetable(&dctx->lenlentable);
                dctx->lenlentable = NULL;
                dctx->state = INBLK;
                freetable(&dctx->lenlentable);
                dctx->lenlentable = NULL;
                dctx->state = INBLK;
@@ -2374,7 +2385,8 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
                    freetable(&dctx->currlentable);
                    dctx->currlentable = NULL;
                }
                    freetable(&dctx->currlentable);
                    dctx->currlentable = NULL;
                }
-               if (dctx->currdisttable != dctx->staticdisttable) {
+               if (dctx->currdisttable &&
+                    dctx->currdisttable != dctx->staticdisttable) {
                    freetable(&dctx->currdisttable);
                    dctx->currdisttable = NULL;
                }
                    freetable(&dctx->currdisttable);
                    dctx->currdisttable = NULL;
                }
@@ -2396,6 +2408,10 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
            dctx->state = GOTLEN;
            break;
          case GOTLEN:
            dctx->state = GOTLEN;
            break;
          case GOTLEN:
+            if (!dctx->currdisttable) {
+               error = DEFLATE_ERR_NODISTTABLE;
+                goto finished;
+            }
            code = huflookup(&dctx->bits, &dctx->nbits, dctx->currdisttable);
            debug(("recv: dist %d\n", code));
            if (code == -1)
            code = huflookup(&dctx->bits, &dctx->nbits, dctx->currdisttable);
            debug(("recv: dist %d\n", code));
            if (code == -1)
index 6f51407..140626f 100644 (file)
--- a/deflate.h
+++ b/deflate.h
@@ -151,6 +151,7 @@ int deflate_decompress_data(deflate_decompress_ctx *ctx,
     A(DEFLATE_ERR_SMALL_HUFTABLE, "under-committed Huffman code space"), \
     A(DEFLATE_ERR_LARGE_HUFTABLE, "over-committed Huffman code space"), \
     A(DEFLATE_ERR_UNCOMP_HDR, "wrongly formatted header in uncompressed block"), \
     A(DEFLATE_ERR_SMALL_HUFTABLE, "under-committed Huffman code space"), \
     A(DEFLATE_ERR_LARGE_HUFTABLE, "over-committed Huffman code space"), \
     A(DEFLATE_ERR_UNCOMP_HDR, "wrongly formatted header in uncompressed block"), \
+    A(DEFLATE_ERR_NODISTTABLE, "backward copy encoded in block without distances table"), \
     A(DEFLATE_ERR_CHECKSUM, "incorrect data checksum"), \
     A(DEFLATE_ERR_INLEN, "incorrect data length"), \
     A(DEFLATE_ERR_UNEXPECTED_EOF, "unexpected end of data")
     A(DEFLATE_ERR_CHECKSUM, "incorrect data checksum"), \
     A(DEFLATE_ERR_INLEN, "incorrect data length"), \
     A(DEFLATE_ERR_UNEXPECTED_EOF, "unexpected end of data")