summaryrefslogtreecommitdiff
path: root/deflate.c
diff options
context:
space:
mode:
authorSimon Tatham <anakin@pobox.com>2012-06-01 19:37:14 +0000
committerSimon Tatham <anakin@pobox.com>2012-06-01 19:37:14 +0000
commitea4654d03324dd4feba49d616cbf13b4d6b808c6 (patch)
treeca37d46073194792bb211aaab70ca89282bc3125 /deflate.c
parent7c09a2ba4b42aa86785e788a5c72cc1e628d7d9a (diff)
downloadhalibut-ea4654d03324dd4feba49d616cbf13b4d6b808c6.zip
halibut-ea4654d03324dd4feba49d616cbf13b4d6b808c6.tar.gz
halibut-ea4654d03324dd4feba49d616cbf13b4d6b808c6.tar.bz2
halibut-ea4654d03324dd4feba49d616cbf13b4d6b808c6.tar.xz
Make the Deflate decoder correctly handle the special case of a
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.) [originally from svn r9550]
Diffstat (limited to 'deflate.c')
-rw-r--r--deflate.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/deflate.c b/deflate.c
index d614c37..186e14c 100644
--- 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 */
- 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
- "distance",
+ "distance",
#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;
@@ -2374,7 +2385,8 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
freetable(&dctx->currlentable);
dctx->currlentable = NULL;
}
- if (dctx->currdisttable != dctx->staticdisttable) {
+ if (dctx->currdisttable &&
+ dctx->currdisttable != dctx->staticdisttable) {
freetable(&dctx->currdisttable);
dctx->currdisttable = NULL;
}
@@ -2396,6 +2408,10 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
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)