|
@@ -1,18 +1,18 @@
|
|
|
/*
|
|
|
* Zlib (RFC1950 / RFC1951) compression for PuTTY.
|
|
|
- *
|
|
|
+ *
|
|
|
* There will no doubt be criticism of my decision to reimplement
|
|
|
* Zlib compression from scratch instead of using the existing zlib
|
|
|
* code. People will cry `reinventing the wheel'; they'll claim
|
|
|
* that the `fundamental basis of OSS' is code reuse; they'll want
|
|
|
* to see a really good reason for me having chosen not to use the
|
|
|
* existing code.
|
|
|
- *
|
|
|
+ *
|
|
|
* Well, here are my reasons. Firstly, I don't want to link the
|
|
|
* whole of zlib into the PuTTY binary; PuTTY is justifiably proud
|
|
|
* of its small size and I think zlib contains a lot of unnecessary
|
|
|
* baggage for the kind of compression that SSH requires.
|
|
|
- *
|
|
|
+ *
|
|
|
* Secondly, I also don't like the alternative of using zlib.dll.
|
|
|
* Another thing PuTTY is justifiably proud of is its ease of
|
|
|
* installation, and the last thing I want to do is to start
|
|
@@ -20,7 +20,7 @@
|
|
|
* zlib.dll kicking around, one with C calling conventions on the
|
|
|
* exported functions and another with WINAPI conventions, and
|
|
|
* there would be a significant danger of getting the wrong one.
|
|
|
- *
|
|
|
+ *
|
|
|
* Thirdly, there seems to be a difference of opinion on the IETF
|
|
|
* secsh mailing list about the correct way to round off a
|
|
|
* compressed packet and start the next. In particular, there's
|
|
@@ -28,7 +28,7 @@
|
|
|
* capable of supporting (see below for an explanation). Given that
|
|
|
* sort of uncertainty, I thought it might be better to have code
|
|
|
* that will support even the zlib-incompatible worst case.
|
|
|
- *
|
|
|
+ *
|
|
|
* Fourthly, it's a _second implementation_. Second implementations
|
|
|
* are fundamentally a Good Thing in standardisation efforts. The
|
|
|
* difference of opinion mentioned above has arisen _precisely_
|
|
@@ -71,15 +71,15 @@ static int lz77_init(struct LZ77Context *ctx);
|
|
|
* instead call literal() for everything.
|
|
|
*/
|
|
|
static void lz77_compress(struct LZ77Context *ctx,
|
|
|
- const unsigned char *data, int len);
|
|
|
+ const unsigned char *data, int len);
|
|
|
|
|
|
/*
|
|
|
* Modifiable parameters.
|
|
|
*/
|
|
|
-#define WINSIZE 32768 /* window size. Must be power of 2! */
|
|
|
-#define HASHMAX 2039 /* one more than max hash value */
|
|
|
-#define MAXMATCH 32 /* how many matches we track */
|
|
|
-#define HASHCHARS 3 /* how many chars make a hash */
|
|
|
+#define WINSIZE 32768 /* window size. Must be power of 2! */
|
|
|
+#define HASHMAX 2039 /* one more than max hash value */
|
|
|
+#define MAXMATCH 32 /* how many matches we track */
|
|
|
+#define HASHCHARS 3 /* how many chars make a hash */
|
|
|
|
|
|
/*
|
|
|
* This compressor takes a less slapdash approach than the
|
|
@@ -90,14 +90,14 @@ static void lz77_compress(struct LZ77Context *ctx,
|
|
|
* byte), we can carefully remove the hash chain entry.
|
|
|
*/
|
|
|
|
|
|
-#define INVALID -1 /* invalid hash _and_ invalid offset */
|
|
|
+#define INVALID -1 /* invalid hash _and_ invalid offset */
|
|
|
struct WindowEntry {
|
|
|
- short next, prev; /* array indices within the window */
|
|
|
+ short next, prev; /* array indices within the window */
|
|
|
short hashval;
|
|
|
};
|
|
|
|
|
|
struct HashEntry {
|
|
|
- short first; /* window index of first in chain */
|
|
|
+ short first; /* window index of first in chain */
|
|
|
};
|
|
|
|
|
|
struct Match {
|
|
@@ -125,14 +125,14 @@ static int lz77_init(struct LZ77Context *ctx)
|
|
|
|
|
|
st = snew(struct LZ77InternalContext);
|
|
|
if (!st)
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
|
|
|
ctx->ictx = st;
|
|
|
|
|
|
for (i = 0; i < WINSIZE; i++)
|
|
|
- st->win[i].next = st->win[i].prev = st->win[i].hashval = INVALID;
|
|
|
+ st->win[i].next = st->win[i].prev = st->win[i].hashval = INVALID;
|
|
|
for (i = 0; i < HASHMAX; i++)
|
|
|
- st->hashtab[i].first = INVALID;
|
|
|
+ st->hashtab[i].first = INVALID;
|
|
|
st->winpos = 0;
|
|
|
|
|
|
st->npending = 0;
|
|
@@ -141,7 +141,7 @@ static int lz77_init(struct LZ77Context *ctx)
|
|
|
}
|
|
|
|
|
|
static void lz77_advance(struct LZ77InternalContext *st,
|
|
|
- unsigned char c, int hash)
|
|
|
+ unsigned char c, int hash)
|
|
|
{
|
|
|
int off;
|
|
|
|
|
@@ -150,9 +150,9 @@ static void lz77_advance(struct LZ77InternalContext *st,
|
|
|
* or empty the chain if it's the only thing on the chain.
|
|
|
*/
|
|
|
if (st->win[st->winpos].prev != INVALID) {
|
|
|
- st->win[st->win[st->winpos].prev].next = INVALID;
|
|
|
+ st->win[st->win[st->winpos].prev].next = INVALID;
|
|
|
} else if (st->win[st->winpos].hashval != INVALID) {
|
|
|
- st->hashtab[st->win[st->winpos].hashval].first = INVALID;
|
|
|
+ st->hashtab[st->win[st->winpos].hashval].first = INVALID;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -164,7 +164,7 @@ static void lz77_advance(struct LZ77InternalContext *st,
|
|
|
off = st->win[st->winpos].next = st->hashtab[hash].first;
|
|
|
st->hashtab[hash].first = st->winpos;
|
|
|
if (off != INVALID)
|
|
|
- st->win[off].prev = st->winpos;
|
|
|
+ st->win[off].prev = st->winpos;
|
|
|
st->data[st->winpos] = c;
|
|
|
|
|
|
/*
|
|
@@ -176,7 +176,7 @@ static void lz77_advance(struct LZ77InternalContext *st,
|
|
|
#define CHARAT(k) ( (k)<0 ? st->data[(st->winpos+k)&(WINSIZE-1)] : data[k] )
|
|
|
|
|
|
static void lz77_compress(struct LZ77Context *ctx,
|
|
|
- const unsigned char *data, int len)
|
|
|
+ const unsigned char *data, int len)
|
|
|
{
|
|
|
struct LZ77InternalContext *st = ctx->ictx;
|
|
|
int i, distance, off, nmatch, matchlen, advance;
|
|
@@ -195,18 +195,18 @@ static void lz77_compress(struct LZ77Context *ctx,
|
|
|
* HASHCHARS in size.
|
|
|
*/
|
|
|
for (i = 0; i < st->npending; i++) {
|
|
|
- unsigned char foo[HASHCHARS];
|
|
|
- int j;
|
|
|
- if (len + st->npending - i < HASHCHARS) {
|
|
|
- /* Update the pending array. */
|
|
|
- for (j = i; j < st->npending; j++)
|
|
|
- st->pending[j - i] = st->pending[j];
|
|
|
- break;
|
|
|
- }
|
|
|
- for (j = 0; j < HASHCHARS; j++)
|
|
|
- foo[j] = (i + j < st->npending ? st->pending[i + j] :
|
|
|
- data[i + j - st->npending]);
|
|
|
- lz77_advance(st, foo[0], lz77_hash(foo));
|
|
|
+ unsigned char foo[HASHCHARS];
|
|
|
+ int j;
|
|
|
+ if (len + st->npending - i < HASHCHARS) {
|
|
|
+ /* Update the pending array. */
|
|
|
+ for (j = i; j < st->npending; j++)
|
|
|
+ st->pending[j - i] = st->pending[j];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ for (j = 0; j < HASHCHARS; j++)
|
|
|
+ foo[j] = (i + j < st->npending ? st->pending[i + j] :
|
|
|
+ data[i + j - st->npending]);
|
|
|
+ lz77_advance(st, foo[0], lz77_hash(foo));
|
|
|
}
|
|
|
st->npending -= i;
|
|
|
|
|
@@ -215,115 +215,115 @@ static void lz77_compress(struct LZ77Context *ctx,
|
|
|
deferchr = '\0';
|
|
|
while (len > 0) {
|
|
|
|
|
|
- if (len >= HASHCHARS) {
|
|
|
- /*
|
|
|
- * Hash the next few characters.
|
|
|
- */
|
|
|
- int hash = lz77_hash(data);
|
|
|
-
|
|
|
- /*
|
|
|
- * Look the hash up in the corresponding hash chain and see
|
|
|
- * what we can find.
|
|
|
- */
|
|
|
- nmatch = 0;
|
|
|
- for (off = st->hashtab[hash].first;
|
|
|
- off != INVALID; off = st->win[off].next) {
|
|
|
- /* distance = 1 if off == st->winpos-1 */
|
|
|
- /* distance = WINSIZE if off == st->winpos */
|
|
|
- distance =
|
|
|
- WINSIZE - (off + WINSIZE - st->winpos) % WINSIZE;
|
|
|
- for (i = 0; i < HASHCHARS; i++)
|
|
|
- if (CHARAT(i) != CHARAT(i - distance))
|
|
|
- break;
|
|
|
- if (i == HASHCHARS) {
|
|
|
- matches[nmatch].distance = distance;
|
|
|
- matches[nmatch].len = 3;
|
|
|
- if (++nmatch >= MAXMATCH)
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- nmatch = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (nmatch > 0) {
|
|
|
- /*
|
|
|
- * We've now filled up matches[] with nmatch potential
|
|
|
- * matches. Follow them down to find the longest. (We
|
|
|
- * assume here that it's always worth favouring a
|
|
|
- * longer match over a shorter one.)
|
|
|
- */
|
|
|
- matchlen = HASHCHARS;
|
|
|
- while (matchlen < len) {
|
|
|
- int j;
|
|
|
- for (i = j = 0; i < nmatch; i++) {
|
|
|
- if (CHARAT(matchlen) ==
|
|
|
- CHARAT(matchlen - matches[i].distance)) {
|
|
|
- matches[j++] = matches[i];
|
|
|
- }
|
|
|
- }
|
|
|
- if (j == 0)
|
|
|
- break;
|
|
|
- matchlen++;
|
|
|
- nmatch = j;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * We've now got all the longest matches. We favour the
|
|
|
- * shorter distances, which means we go with matches[0].
|
|
|
- * So see if we want to defer it or throw it away.
|
|
|
- */
|
|
|
- matches[0].len = matchlen;
|
|
|
- if (defermatch.len > 0) {
|
|
|
- if (matches[0].len > defermatch.len + 1) {
|
|
|
- /* We have a better match. Emit the deferred char,
|
|
|
- * and defer this match. */
|
|
|
- ctx->literal(ctx, (unsigned char) deferchr);
|
|
|
- defermatch = matches[0];
|
|
|
- deferchr = data[0];
|
|
|
- advance = 1;
|
|
|
- } else {
|
|
|
- /* We don't have a better match. Do the deferred one. */
|
|
|
- ctx->match(ctx, defermatch.distance, defermatch.len);
|
|
|
- advance = defermatch.len - 1;
|
|
|
- defermatch.len = 0;
|
|
|
- }
|
|
|
- } else {
|
|
|
- /* There was no deferred match. Defer this one. */
|
|
|
- defermatch = matches[0];
|
|
|
- deferchr = data[0];
|
|
|
- advance = 1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- /*
|
|
|
- * We found no matches. Emit the deferred match, if
|
|
|
- * any; otherwise emit a literal.
|
|
|
- */
|
|
|
- if (defermatch.len > 0) {
|
|
|
- ctx->match(ctx, defermatch.distance, defermatch.len);
|
|
|
- advance = defermatch.len - 1;
|
|
|
- defermatch.len = 0;
|
|
|
- } else {
|
|
|
- ctx->literal(ctx, data[0]);
|
|
|
- advance = 1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Now advance the position by `advance' characters,
|
|
|
- * keeping the window and hash chains consistent.
|
|
|
- */
|
|
|
- while (advance > 0) {
|
|
|
- if (len >= HASHCHARS) {
|
|
|
- lz77_advance(st, *data, lz77_hash(data));
|
|
|
- } else {
|
|
|
+ if (len >= HASHCHARS) {
|
|
|
+ /*
|
|
|
+ * Hash the next few characters.
|
|
|
+ */
|
|
|
+ int hash = lz77_hash(data);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Look the hash up in the corresponding hash chain and see
|
|
|
+ * what we can find.
|
|
|
+ */
|
|
|
+ nmatch = 0;
|
|
|
+ for (off = st->hashtab[hash].first;
|
|
|
+ off != INVALID; off = st->win[off].next) {
|
|
|
+ /* distance = 1 if off == st->winpos-1 */
|
|
|
+ /* distance = WINSIZE if off == st->winpos */
|
|
|
+ distance =
|
|
|
+ WINSIZE - (off + WINSIZE - st->winpos) % WINSIZE;
|
|
|
+ for (i = 0; i < HASHCHARS; i++)
|
|
|
+ if (CHARAT(i) != CHARAT(i - distance))
|
|
|
+ break;
|
|
|
+ if (i == HASHCHARS) {
|
|
|
+ matches[nmatch].distance = distance;
|
|
|
+ matches[nmatch].len = 3;
|
|
|
+ if (++nmatch >= MAXMATCH)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ nmatch = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nmatch > 0) {
|
|
|
+ /*
|
|
|
+ * We've now filled up matches[] with nmatch potential
|
|
|
+ * matches. Follow them down to find the longest. (We
|
|
|
+ * assume here that it's always worth favouring a
|
|
|
+ * longer match over a shorter one.)
|
|
|
+ */
|
|
|
+ matchlen = HASHCHARS;
|
|
|
+ while (matchlen < len) {
|
|
|
+ int j;
|
|
|
+ for (i = j = 0; i < nmatch; i++) {
|
|
|
+ if (CHARAT(matchlen) ==
|
|
|
+ CHARAT(matchlen - matches[i].distance)) {
|
|
|
+ matches[j++] = matches[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (j == 0)
|
|
|
+ break;
|
|
|
+ matchlen++;
|
|
|
+ nmatch = j;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We've now got all the longest matches. We favour the
|
|
|
+ * shorter distances, which means we go with matches[0].
|
|
|
+ * So see if we want to defer it or throw it away.
|
|
|
+ */
|
|
|
+ matches[0].len = matchlen;
|
|
|
+ if (defermatch.len > 0) {
|
|
|
+ if (matches[0].len > defermatch.len + 1) {
|
|
|
+ /* We have a better match. Emit the deferred char,
|
|
|
+ * and defer this match. */
|
|
|
+ ctx->literal(ctx, (unsigned char) deferchr);
|
|
|
+ defermatch = matches[0];
|
|
|
+ deferchr = data[0];
|
|
|
+ advance = 1;
|
|
|
+ } else {
|
|
|
+ /* We don't have a better match. Do the deferred one. */
|
|
|
+ ctx->match(ctx, defermatch.distance, defermatch.len);
|
|
|
+ advance = defermatch.len - 1;
|
|
|
+ defermatch.len = 0;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* There was no deferred match. Defer this one. */
|
|
|
+ defermatch = matches[0];
|
|
|
+ deferchr = data[0];
|
|
|
+ advance = 1;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * We found no matches. Emit the deferred match, if
|
|
|
+ * any; otherwise emit a literal.
|
|
|
+ */
|
|
|
+ if (defermatch.len > 0) {
|
|
|
+ ctx->match(ctx, defermatch.distance, defermatch.len);
|
|
|
+ advance = defermatch.len - 1;
|
|
|
+ defermatch.len = 0;
|
|
|
+ } else {
|
|
|
+ ctx->literal(ctx, data[0]);
|
|
|
+ advance = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Now advance the position by `advance' characters,
|
|
|
+ * keeping the window and hash chains consistent.
|
|
|
+ */
|
|
|
+ while (advance > 0) {
|
|
|
+ if (len >= HASHCHARS) {
|
|
|
+ lz77_advance(st, *data, lz77_hash(data));
|
|
|
+ } else {
|
|
|
assert(st->npending < HASHCHARS);
|
|
|
- st->pending[st->npending++] = *data;
|
|
|
- }
|
|
|
- data++;
|
|
|
- len--;
|
|
|
- advance--;
|
|
|
- }
|
|
|
+ st->pending[st->npending++] = *data;
|
|
|
+ }
|
|
|
+ data++;
|
|
|
+ len--;
|
|
|
+ advance--;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -334,7 +334,7 @@ static void lz77_compress(struct LZ77Context *ctx,
|
|
|
* compressing a large file under no significant time constraint,
|
|
|
* but when you're compressing little bits in real time, things get
|
|
|
* hairier.
|
|
|
- *
|
|
|
+ *
|
|
|
* I suppose it's possible that I could compute Huffman trees based
|
|
|
* on the frequencies in the _previous_ block, as a sort of
|
|
|
* heuristic, but I'm not confident that the gain would balance out
|
|
@@ -355,8 +355,8 @@ static void outbits(struct Outbuf *out, unsigned long bits, int nbits)
|
|
|
out->noutbits += nbits;
|
|
|
while (out->noutbits >= 8) {
|
|
|
put_byte(out->outbuf, out->outbits & 0xFF);
|
|
|
- out->outbits >>= 8;
|
|
|
- out->noutbits -= 8;
|
|
|
+ out->outbits >>= 8;
|
|
|
+ out->noutbits -= 8;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -470,11 +470,11 @@ static void zlib_literal(struct LZ77Context *ectx, unsigned char c)
|
|
|
struct Outbuf *out = (struct Outbuf *) ectx->userdata;
|
|
|
|
|
|
if (c <= 143) {
|
|
|
- /* 0 through 143 are 8 bits long starting at 00110000. */
|
|
|
- outbits(out, mirrorbytes[0x30 + c], 8);
|
|
|
+ /* 0 through 143 are 8 bits long starting at 00110000. */
|
|
|
+ outbits(out, mirrorbytes[0x30 + c], 8);
|
|
|
} else {
|
|
|
- /* 144 through 255 are 9 bits long starting at 110010000. */
|
|
|
- outbits(out, 1 + 2 * mirrorbytes[0x90 - 144 + c], 9);
|
|
|
+ /* 144 through 255 are 9 bits long starting at 110010000. */
|
|
|
+ outbits(out, 1 + 2 * mirrorbytes[0x90 - 144 + c], 9);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -485,86 +485,86 @@ static void zlib_match(struct LZ77Context *ectx, int distance, int len)
|
|
|
struct Outbuf *out = (struct Outbuf *) ectx->userdata;
|
|
|
|
|
|
while (len > 0) {
|
|
|
- int thislen;
|
|
|
-
|
|
|
- /*
|
|
|
- * We can transmit matches of lengths 3 through 258
|
|
|
- * inclusive. So if len exceeds 258, we must transmit in
|
|
|
- * several steps, with 258 or less in each step.
|
|
|
- *
|
|
|
- * Specifically: if len >= 261, we can transmit 258 and be
|
|
|
- * sure of having at least 3 left for the next step. And if
|
|
|
- * len <= 258, we can just transmit len. But if len == 259
|
|
|
- * or 260, we must transmit len-3.
|
|
|
- */
|
|
|
- thislen = (len > 260 ? 258 : len <= 258 ? len : len - 3);
|
|
|
- len -= thislen;
|
|
|
-
|
|
|
- /*
|
|
|
- * Binary-search to find which length code we're
|
|
|
- * transmitting.
|
|
|
- */
|
|
|
- i = -1;
|
|
|
- j = lenof(lencodes);
|
|
|
- while (1) {
|
|
|
- assert(j - i >= 2);
|
|
|
- k = (j + i) / 2;
|
|
|
- if (thislen < lencodes[k].min)
|
|
|
- j = k;
|
|
|
- else if (thislen > lencodes[k].max)
|
|
|
- i = k;
|
|
|
- else {
|
|
|
- l = &lencodes[k];
|
|
|
- break; /* found it! */
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Transmit the length code. 256-279 are seven bits
|
|
|
- * starting at 0000000; 280-287 are eight bits starting at
|
|
|
- * 11000000.
|
|
|
- */
|
|
|
- if (l->code <= 279) {
|
|
|
- outbits(out, mirrorbytes[(l->code - 256) * 2], 7);
|
|
|
- } else {
|
|
|
- outbits(out, mirrorbytes[0xc0 - 280 + l->code], 8);
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Transmit the extra bits.
|
|
|
- */
|
|
|
- if (l->extrabits)
|
|
|
- outbits(out, thislen - l->min, l->extrabits);
|
|
|
-
|
|
|
- /*
|
|
|
- * Binary-search to find which distance code we're
|
|
|
- * transmitting.
|
|
|
- */
|
|
|
- i = -1;
|
|
|
- j = lenof(distcodes);
|
|
|
- while (1) {
|
|
|
- assert(j - i >= 2);
|
|
|
- k = (j + i) / 2;
|
|
|
- if (distance < distcodes[k].min)
|
|
|
- j = k;
|
|
|
- else if (distance > distcodes[k].max)
|
|
|
- i = k;
|
|
|
- else {
|
|
|
- d = &distcodes[k];
|
|
|
- break; /* found it! */
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Transmit the distance code. Five bits starting at 00000.
|
|
|
- */
|
|
|
- outbits(out, mirrorbytes[d->code * 8], 5);
|
|
|
-
|
|
|
- /*
|
|
|
- * Transmit the extra bits.
|
|
|
- */
|
|
|
- if (d->extrabits)
|
|
|
- outbits(out, distance - d->min, d->extrabits);
|
|
|
+ int thislen;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We can transmit matches of lengths 3 through 258
|
|
|
+ * inclusive. So if len exceeds 258, we must transmit in
|
|
|
+ * several steps, with 258 or less in each step.
|
|
|
+ *
|
|
|
+ * Specifically: if len >= 261, we can transmit 258 and be
|
|
|
+ * sure of having at least 3 left for the next step. And if
|
|
|
+ * len <= 258, we can just transmit len. But if len == 259
|
|
|
+ * or 260, we must transmit len-3.
|
|
|
+ */
|
|
|
+ thislen = (len > 260 ? 258 : len <= 258 ? len : len - 3);
|
|
|
+ len -= thislen;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Binary-search to find which length code we're
|
|
|
+ * transmitting.
|
|
|
+ */
|
|
|
+ i = -1;
|
|
|
+ j = lenof(lencodes);
|
|
|
+ while (1) {
|
|
|
+ assert(j - i >= 2);
|
|
|
+ k = (j + i) / 2;
|
|
|
+ if (thislen < lencodes[k].min)
|
|
|
+ j = k;
|
|
|
+ else if (thislen > lencodes[k].max)
|
|
|
+ i = k;
|
|
|
+ else {
|
|
|
+ l = &lencodes[k];
|
|
|
+ break; /* found it! */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Transmit the length code. 256-279 are seven bits
|
|
|
+ * starting at 0000000; 280-287 are eight bits starting at
|
|
|
+ * 11000000.
|
|
|
+ */
|
|
|
+ if (l->code <= 279) {
|
|
|
+ outbits(out, mirrorbytes[(l->code - 256) * 2], 7);
|
|
|
+ } else {
|
|
|
+ outbits(out, mirrorbytes[0xc0 - 280 + l->code], 8);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Transmit the extra bits.
|
|
|
+ */
|
|
|
+ if (l->extrabits)
|
|
|
+ outbits(out, thislen - l->min, l->extrabits);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Binary-search to find which distance code we're
|
|
|
+ * transmitting.
|
|
|
+ */
|
|
|
+ i = -1;
|
|
|
+ j = lenof(distcodes);
|
|
|
+ while (1) {
|
|
|
+ assert(j - i >= 2);
|
|
|
+ k = (j + i) / 2;
|
|
|
+ if (distance < distcodes[k].min)
|
|
|
+ j = k;
|
|
|
+ else if (distance > distcodes[k].max)
|
|
|
+ i = k;
|
|
|
+ else {
|
|
|
+ d = &distcodes[k];
|
|
|
+ break; /* found it! */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Transmit the distance code. Five bits starting at 00000.
|
|
|
+ */
|
|
|
+ outbits(out, mirrorbytes[d->code * 8], 5);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Transmit the extra bits.
|
|
|
+ */
|
|
|
+ if (d->extrabits)
|
|
|
+ outbits(out, distance - d->min, d->extrabits);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -623,12 +623,12 @@ void zlib_compress_block(ssh_compressor *sc,
|
|
|
* algorithm.)
|
|
|
*/
|
|
|
if (out->firstblock) {
|
|
|
- outbits(out, 0x9C78, 16);
|
|
|
- out->firstblock = false;
|
|
|
+ outbits(out, 0x9C78, 16);
|
|
|
+ out->firstblock = false;
|
|
|
|
|
|
- in_block = false;
|
|
|
+ in_block = false;
|
|
|
} else
|
|
|
- in_block = true;
|
|
|
+ in_block = true;
|
|
|
|
|
|
if (!in_block) {
|
|
|
/*
|
|
@@ -668,9 +668,9 @@ void zlib_compress_block(ssh_compressor *sc,
|
|
|
*
|
|
|
* For the moment, we will use Zlib partial flush.
|
|
|
*/
|
|
|
- outbits(out, 0, 7); /* close block */
|
|
|
+ outbits(out, 0, 7); /* close block */
|
|
|
outbits(out, 2, 3 + 7); /* empty static block */
|
|
|
- outbits(out, 2, 3); /* open new block */
|
|
|
+ outbits(out, 2, 3); /* open new block */
|
|
|
|
|
|
/*
|
|
|
* If we've been asked to pad out the compressed data until it's
|
|
@@ -678,8 +678,8 @@ void zlib_compress_block(ssh_compressor *sc,
|
|
|
* blocks.
|
|
|
*/
|
|
|
while (out->outbuf->len < minlen) {
|
|
|
- outbits(out, 0, 7); /* close block */
|
|
|
- outbits(out, 2, 3); /* open new static block */
|
|
|
+ outbits(out, 0, 7); /* close block */
|
|
|
+ outbits(out, 2, 3); /* open new static block */
|
|
|
}
|
|
|
|
|
|
*outlen = out->outbuf->len;
|
|
@@ -710,7 +710,7 @@ struct zlib_tableentry {
|
|
|
};
|
|
|
|
|
|
struct zlib_table {
|
|
|
- int mask; /* mask applied to input bit stream */
|
|
|
+ int mask; /* mask applied to input bit stream */
|
|
|
struct zlib_tableentry *table;
|
|
|
};
|
|
|
|
|
@@ -723,8 +723,8 @@ struct zlib_table {
|
|
|
* recurse to build subtables.
|
|
|
*/
|
|
|
static struct zlib_table *zlib_mkonetab(int *codes, unsigned char *lengths,
|
|
|
- int nsyms,
|
|
|
- int pfx, int pfxbits, int bits)
|
|
|
+ int nsyms,
|
|
|
+ int pfx, int pfxbits, int bits)
|
|
|
{
|
|
|
struct zlib_table *tab = snew(struct zlib_table);
|
|
|
int pfxmask = (1 << pfxbits) - 1;
|
|
@@ -734,34 +734,34 @@ static struct zlib_table *zlib_mkonetab(int *codes, unsigned char *lengths,
|
|
|
tab->mask = (1 << bits) - 1;
|
|
|
|
|
|
for (code = 0; code <= tab->mask; code++) {
|
|
|
- tab->table[code].code = -1;
|
|
|
- tab->table[code].nbits = 0;
|
|
|
- tab->table[code].nexttable = NULL;
|
|
|
+ tab->table[code].code = -1;
|
|
|
+ tab->table[code].nbits = 0;
|
|
|
+ tab->table[code].nexttable = NULL;
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < nsyms; i++) {
|
|
|
- if (lengths[i] <= pfxbits || (codes[i] & pfxmask) != pfx)
|
|
|
- continue;
|
|
|
- code = (codes[i] >> pfxbits) & tab->mask;
|
|
|
- for (j = code; j <= tab->mask; j += 1 << (lengths[i] - pfxbits)) {
|
|
|
- tab->table[j].code = i;
|
|
|
- nbits = lengths[i] - pfxbits;
|
|
|
- if (tab->table[j].nbits < nbits)
|
|
|
- tab->table[j].nbits = nbits;
|
|
|
- }
|
|
|
+ if (lengths[i] <= pfxbits || (codes[i] & pfxmask) != pfx)
|
|
|
+ continue;
|
|
|
+ code = (codes[i] >> pfxbits) & tab->mask;
|
|
|
+ for (j = code; j <= tab->mask; j += 1 << (lengths[i] - pfxbits)) {
|
|
|
+ tab->table[j].code = i;
|
|
|
+ nbits = lengths[i] - pfxbits;
|
|
|
+ if (tab->table[j].nbits < nbits)
|
|
|
+ tab->table[j].nbits = nbits;
|
|
|
+ }
|
|
|
}
|
|
|
for (code = 0; code <= tab->mask; code++) {
|
|
|
- if (tab->table[code].nbits <= bits)
|
|
|
- continue;
|
|
|
- /* Generate a subtable. */
|
|
|
- tab->table[code].code = -1;
|
|
|
- nbits = tab->table[code].nbits - bits;
|
|
|
- if (nbits > 7)
|
|
|
- nbits = 7;
|
|
|
- tab->table[code].nbits = bits;
|
|
|
- tab->table[code].nexttable = zlib_mkonetab(codes, lengths, nsyms,
|
|
|
- pfx | (code << pfxbits),
|
|
|
- pfxbits + bits, nbits);
|
|
|
+ if (tab->table[code].nbits <= bits)
|
|
|
+ continue;
|
|
|
+ /* Generate a subtable. */
|
|
|
+ tab->table[code].code = -1;
|
|
|
+ nbits = tab->table[code].nbits - bits;
|
|
|
+ if (nbits > 7)
|
|
|
+ nbits = 7;
|
|
|
+ tab->table[code].nbits = bits;
|
|
|
+ tab->table[code].nexttable = zlib_mkonetab(codes, lengths, nsyms,
|
|
|
+ pfx | (code << pfxbits),
|
|
|
+ pfxbits + bits, nbits);
|
|
|
}
|
|
|
|
|
|
return tab;
|
|
@@ -771,7 +771,7 @@ static struct zlib_table *zlib_mkonetab(int *codes, unsigned char *lengths,
|
|
|
* Build a decode table, given a set of Huffman tree lengths.
|
|
|
*/
|
|
|
static struct zlib_table *zlib_mktable(unsigned char *lengths,
|
|
|
- int nlengths)
|
|
|
+ int nlengths)
|
|
|
{
|
|
|
int count[MAXCODELEN], startcode[MAXCODELEN], codes[MAXSYMS];
|
|
|
int code, maxlen;
|
|
@@ -780,27 +780,27 @@ static struct zlib_table *zlib_mktable(unsigned char *lengths,
|
|
|
/* Count the codes of each length. */
|
|
|
maxlen = 0;
|
|
|
for (i = 1; i < MAXCODELEN; i++)
|
|
|
- count[i] = 0;
|
|
|
+ count[i] = 0;
|
|
|
for (i = 0; i < nlengths; i++) {
|
|
|
- count[lengths[i]]++;
|
|
|
- if (maxlen < lengths[i])
|
|
|
- maxlen = lengths[i];
|
|
|
+ count[lengths[i]]++;
|
|
|
+ if (maxlen < lengths[i])
|
|
|
+ maxlen = lengths[i];
|
|
|
}
|
|
|
/* Determine the starting code for each length block. */
|
|
|
code = 0;
|
|
|
for (i = 1; i < MAXCODELEN; i++) {
|
|
|
- startcode[i] = code;
|
|
|
- code += count[i];
|
|
|
- code <<= 1;
|
|
|
+ startcode[i] = code;
|
|
|
+ code += count[i];
|
|
|
+ code <<= 1;
|
|
|
}
|
|
|
/* Determine the code for each symbol. Mirrored, of course. */
|
|
|
for (i = 0; i < nlengths; i++) {
|
|
|
- code = startcode[lengths[i]]++;
|
|
|
- codes[i] = 0;
|
|
|
- for (j = 0; j < lengths[i]; j++) {
|
|
|
- codes[i] = (codes[i] << 1) | (code & 1);
|
|
|
- code >>= 1;
|
|
|
- }
|
|
|
+ code = startcode[lengths[i]]++;
|
|
|
+ codes[i] = 0;
|
|
|
+ for (j = 0; j < lengths[i]; j++) {
|
|
|
+ codes[i] = (codes[i] << 1) | (code & 1);
|
|
|
+ code >>= 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -808,7 +808,7 @@ static struct zlib_table *zlib_mktable(unsigned char *lengths,
|
|
|
* table.
|
|
|
*/
|
|
|
return zlib_mkonetab(codes, lengths, nlengths, 0, 0,
|
|
|
- maxlen < 9 ? maxlen : 9);
|
|
|
+ maxlen < 9 ? maxlen : 9);
|
|
|
}
|
|
|
|
|
|
static int zlib_freetable(struct zlib_table **ztab)
|
|
@@ -817,16 +817,16 @@ static int zlib_freetable(struct zlib_table **ztab)
|
|
|
int code;
|
|
|
|
|
|
if (ztab == NULL)
|
|
|
- return -1;
|
|
|
+ return -1;
|
|
|
|
|
|
if (*ztab == NULL)
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
|
|
|
tab = *ztab;
|
|
|
|
|
|
for (code = 0; code <= tab->mask; code++)
|
|
|
- if (tab->table[code].nexttable != NULL)
|
|
|
- zlib_freetable(&tab->table[code].nexttable);
|
|
|
+ if (tab->table[code].nexttable != NULL)
|
|
|
+ zlib_freetable(&tab->table[code].nexttable);
|
|
|
|
|
|
sfree(tab->table);
|
|
|
tab->table = NULL;
|
|
@@ -841,13 +841,13 @@ struct zlib_decompress_ctx {
|
|
|
struct zlib_table *staticlentable, *staticdisttable;
|
|
|
struct zlib_table *currlentable, *currdisttable, *lenlentable;
|
|
|
enum {
|
|
|
- START, OUTSIDEBLK,
|
|
|
- TREES_HDR, TREES_LENLEN, TREES_LEN, TREES_LENREP,
|
|
|
- INBLK, GOTLENSYM, GOTLEN, GOTDISTSYM,
|
|
|
- UNCOMP_LEN, UNCOMP_NLEN, UNCOMP_DATA
|
|
|
+ START, OUTSIDEBLK,
|
|
|
+ TREES_HDR, TREES_LENLEN, TREES_LEN, TREES_LENREP,
|
|
|
+ INBLK, GOTLENSYM, GOTLEN, GOTDISTSYM,
|
|
|
+ UNCOMP_LEN, UNCOMP_NLEN, UNCOMP_DATA
|
|
|
} state;
|
|
|
int sym, hlit, hdist, hclen, lenptr, lenextrabits, lenaddon, len,
|
|
|
- lenrep;
|
|
|
+ lenrep;
|
|
|
int uncomplen;
|
|
|
unsigned char lenlen[19];
|
|
|
|
|
@@ -916,7 +916,7 @@ ssh_decompressor *zlib_decompress_init(void)
|
|
|
dctx->staticlentable = zlib_mktable(lengths, 288);
|
|
|
memset(lengths, 5, 32);
|
|
|
dctx->staticdisttable = zlib_mktable(lengths, 32);
|
|
|
- dctx->state = START; /* even before header */
|
|
|
+ dctx->state = START; /* even before header */
|
|
|
dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL;
|
|
|
dctx->bits = 0;
|
|
|
dctx->nbits = 0;
|
|
@@ -933,11 +933,11 @@ void zlib_decompress_cleanup(ssh_decompressor *dc)
|
|
|
container_of(dc, struct zlib_decompress_ctx, dc);
|
|
|
|
|
|
if (dctx->currlentable && dctx->currlentable != dctx->staticlentable)
|
|
|
- zlib_freetable(&dctx->currlentable);
|
|
|
+ zlib_freetable(&dctx->currlentable);
|
|
|
if (dctx->currdisttable && dctx->currdisttable != dctx->staticdisttable)
|
|
|
- zlib_freetable(&dctx->currdisttable);
|
|
|
+ zlib_freetable(&dctx->currdisttable);
|
|
|
if (dctx->lenlentable)
|
|
|
- zlib_freetable(&dctx->lenlentable);
|
|
|
+ zlib_freetable(&dctx->lenlentable);
|
|
|
zlib_freetable(&dctx->staticlentable);
|
|
|
zlib_freetable(&dctx->staticdisttable);
|
|
|
if (dctx->outblk)
|
|
@@ -946,34 +946,34 @@ void zlib_decompress_cleanup(ssh_decompressor *dc)
|
|
|
}
|
|
|
|
|
|
static int zlib_huflookup(unsigned long *bitsp, int *nbitsp,
|
|
|
- struct zlib_table *tab)
|
|
|
+ struct zlib_table *tab)
|
|
|
{
|
|
|
unsigned long bits = *bitsp;
|
|
|
int nbits = *nbitsp;
|
|
|
while (1) {
|
|
|
- struct zlib_tableentry *ent;
|
|
|
- ent = &tab->table[bits & tab->mask];
|
|
|
- if (ent->nbits > nbits)
|
|
|
- return -1; /* not enough data */
|
|
|
- bits >>= ent->nbits;
|
|
|
- nbits -= ent->nbits;
|
|
|
- if (ent->code == -1)
|
|
|
- tab = ent->nexttable;
|
|
|
- else {
|
|
|
- *bitsp = bits;
|
|
|
- *nbitsp = nbits;
|
|
|
- return ent->code;
|
|
|
- }
|
|
|
-
|
|
|
- if (!tab) {
|
|
|
- /*
|
|
|
- * There was a missing entry in the table, presumably
|
|
|
- * due to an invalid Huffman table description, and the
|
|
|
- * subsequent data has attempted to use the missing
|
|
|
- * entry. Return a decoding failure.
|
|
|
- */
|
|
|
- return -2;
|
|
|
- }
|
|
|
+ struct zlib_tableentry *ent;
|
|
|
+ ent = &tab->table[bits & tab->mask];
|
|
|
+ if (ent->nbits > nbits)
|
|
|
+ return -1; /* not enough data */
|
|
|
+ bits >>= ent->nbits;
|
|
|
+ nbits -= ent->nbits;
|
|
|
+ if (ent->code == -1)
|
|
|
+ tab = ent->nexttable;
|
|
|
+ else {
|
|
|
+ *bitsp = bits;
|
|
|
+ *nbitsp = nbits;
|
|
|
+ return ent->code;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!tab) {
|
|
|
+ /*
|
|
|
+ * There was a missing entry in the table, presumably
|
|
|
+ * due to an invalid Huffman table description, and the
|
|
|
+ * subsequent data has attempted to use the missing
|
|
|
+ * entry. Return a decoding failure.
|
|
|
+ */
|
|
|
+ return -2;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -995,23 +995,23 @@ bool zlib_decompress_block(ssh_decompressor *dc,
|
|
|
const coderecord *rec;
|
|
|
int code, blktype, rep, dist, nlen, header;
|
|
|
static const unsigned char lenlenmap[] = {
|
|
|
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
|
|
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
|
|
};
|
|
|
|
|
|
assert(!dctx->outblk);
|
|
|
dctx->outblk = strbuf_new_nm();
|
|
|
|
|
|
while (len > 0 || dctx->nbits > 0) {
|
|
|
- while (dctx->nbits < 24 && len > 0) {
|
|
|
- dctx->bits |= (*block++) << dctx->nbits;
|
|
|
- dctx->nbits += 8;
|
|
|
- len--;
|
|
|
- }
|
|
|
- switch (dctx->state) {
|
|
|
- case START:
|
|
|
- /* Expect 16-bit zlib header. */
|
|
|
- if (dctx->nbits < 16)
|
|
|
- goto finished; /* done all we can */
|
|
|
+ while (dctx->nbits < 24 && len > 0) {
|
|
|
+ dctx->bits |= (*block++) << dctx->nbits;
|
|
|
+ dctx->nbits += 8;
|
|
|
+ len--;
|
|
|
+ }
|
|
|
+ switch (dctx->state) {
|
|
|
+ case START:
|
|
|
+ /* Expect 16-bit zlib header. */
|
|
|
+ if (dctx->nbits < 16)
|
|
|
+ goto finished; /* done all we can */
|
|
|
|
|
|
/*
|
|
|
* The header is stored as a big-endian 16-bit integer,
|
|
@@ -1038,194 +1038,194 @@ bool zlib_decompress_block(ssh_decompressor *dc,
|
|
|
(header % 31) != 0)
|
|
|
goto decode_error;
|
|
|
|
|
|
- dctx->state = OUTSIDEBLK;
|
|
|
- break;
|
|
|
- case OUTSIDEBLK:
|
|
|
- /* Expect 3-bit block header. */
|
|
|
- if (dctx->nbits < 3)
|
|
|
- goto finished; /* done all we can */
|
|
|
- EATBITS(1);
|
|
|
- blktype = dctx->bits & 3;
|
|
|
- EATBITS(2);
|
|
|
- if (blktype == 0) {
|
|
|
- int to_eat = dctx->nbits & 7;
|
|
|
- dctx->state = UNCOMP_LEN;
|
|
|
- EATBITS(to_eat); /* align to byte boundary */
|
|
|
- } else if (blktype == 1) {
|
|
|
- dctx->currlentable = dctx->staticlentable;
|
|
|
- dctx->currdisttable = dctx->staticdisttable;
|
|
|
- dctx->state = INBLK;
|
|
|
- } else if (blktype == 2) {
|
|
|
- dctx->state = TREES_HDR;
|
|
|
- }
|
|
|
- break;
|
|
|
- case TREES_HDR:
|
|
|
- /*
|
|
|
- * Dynamic block header. Five bits of HLIT, five of
|
|
|
- * HDIST, four of HCLEN.
|
|
|
- */
|
|
|
- if (dctx->nbits < 5 + 5 + 4)
|
|
|
- goto finished; /* done all we can */
|
|
|
- dctx->hlit = 257 + (dctx->bits & 31);
|
|
|
- EATBITS(5);
|
|
|
- dctx->hdist = 1 + (dctx->bits & 31);
|
|
|
- EATBITS(5);
|
|
|
- dctx->hclen = 4 + (dctx->bits & 15);
|
|
|
- EATBITS(4);
|
|
|
- dctx->lenptr = 0;
|
|
|
- dctx->state = TREES_LENLEN;
|
|
|
- memset(dctx->lenlen, 0, sizeof(dctx->lenlen));
|
|
|
- break;
|
|
|
- case TREES_LENLEN:
|
|
|
- if (dctx->nbits < 3)
|
|
|
- goto finished;
|
|
|
- while (dctx->lenptr < dctx->hclen && dctx->nbits >= 3) {
|
|
|
- dctx->lenlen[lenlenmap[dctx->lenptr++]] =
|
|
|
- (unsigned char) (dctx->bits & 7);
|
|
|
- EATBITS(3);
|
|
|
- }
|
|
|
- if (dctx->lenptr == dctx->hclen) {
|
|
|
- dctx->lenlentable = zlib_mktable(dctx->lenlen, 19);
|
|
|
- dctx->state = TREES_LEN;
|
|
|
- dctx->lenptr = 0;
|
|
|
- }
|
|
|
- break;
|
|
|
- case TREES_LEN:
|
|
|
- if (dctx->lenptr >= dctx->hlit + dctx->hdist) {
|
|
|
- dctx->currlentable = zlib_mktable(dctx->lengths, dctx->hlit);
|
|
|
- dctx->currdisttable = zlib_mktable(dctx->lengths + dctx->hlit,
|
|
|
- dctx->hdist);
|
|
|
- zlib_freetable(&dctx->lenlentable);
|
|
|
- dctx->lenlentable = NULL;
|
|
|
- dctx->state = INBLK;
|
|
|
- break;
|
|
|
- }
|
|
|
- code =
|
|
|
- zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->lenlentable);
|
|
|
- if (code == -1)
|
|
|
- goto finished;
|
|
|
- if (code == -2)
|
|
|
- goto decode_error;
|
|
|
- if (code < 16)
|
|
|
- dctx->lengths[dctx->lenptr++] = code;
|
|
|
- else {
|
|
|
- dctx->lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
|
|
- dctx->lenaddon = (code == 18 ? 11 : 3);
|
|
|
- dctx->lenrep = (code == 16 && dctx->lenptr > 0 ?
|
|
|
- dctx->lengths[dctx->lenptr - 1] : 0);
|
|
|
- dctx->state = TREES_LENREP;
|
|
|
- }
|
|
|
- break;
|
|
|
- case TREES_LENREP:
|
|
|
- if (dctx->nbits < dctx->lenextrabits)
|
|
|
- goto finished;
|
|
|
- rep =
|
|
|
- dctx->lenaddon +
|
|
|
- (dctx->bits & ((1 << dctx->lenextrabits) - 1));
|
|
|
- EATBITS(dctx->lenextrabits);
|
|
|
- while (rep > 0 && dctx->lenptr < dctx->hlit + dctx->hdist) {
|
|
|
- dctx->lengths[dctx->lenptr] = dctx->lenrep;
|
|
|
- dctx->lenptr++;
|
|
|
- rep--;
|
|
|
- }
|
|
|
- dctx->state = TREES_LEN;
|
|
|
- break;
|
|
|
- case INBLK:
|
|
|
- code =
|
|
|
- zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->currlentable);
|
|
|
- if (code == -1)
|
|
|
- goto finished;
|
|
|
- if (code == -2)
|
|
|
- goto decode_error;
|
|
|
- if (code < 256)
|
|
|
- zlib_emit_char(dctx, code);
|
|
|
- else if (code == 256) {
|
|
|
- dctx->state = OUTSIDEBLK;
|
|
|
- if (dctx->currlentable != dctx->staticlentable) {
|
|
|
- zlib_freetable(&dctx->currlentable);
|
|
|
- dctx->currlentable = NULL;
|
|
|
- }
|
|
|
- if (dctx->currdisttable != dctx->staticdisttable) {
|
|
|
- zlib_freetable(&dctx->currdisttable);
|
|
|
- dctx->currdisttable = NULL;
|
|
|
- }
|
|
|
- } else if (code < 286) {
|
|
|
- dctx->state = GOTLENSYM;
|
|
|
- dctx->sym = code;
|
|
|
- } else {
|
|
|
+ dctx->state = OUTSIDEBLK;
|
|
|
+ break;
|
|
|
+ case OUTSIDEBLK:
|
|
|
+ /* Expect 3-bit block header. */
|
|
|
+ if (dctx->nbits < 3)
|
|
|
+ goto finished; /* done all we can */
|
|
|
+ EATBITS(1);
|
|
|
+ blktype = dctx->bits & 3;
|
|
|
+ EATBITS(2);
|
|
|
+ if (blktype == 0) {
|
|
|
+ int to_eat = dctx->nbits & 7;
|
|
|
+ dctx->state = UNCOMP_LEN;
|
|
|
+ EATBITS(to_eat); /* align to byte boundary */
|
|
|
+ } else if (blktype == 1) {
|
|
|
+ dctx->currlentable = dctx->staticlentable;
|
|
|
+ dctx->currdisttable = dctx->staticdisttable;
|
|
|
+ dctx->state = INBLK;
|
|
|
+ } else if (blktype == 2) {
|
|
|
+ dctx->state = TREES_HDR;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case TREES_HDR:
|
|
|
+ /*
|
|
|
+ * Dynamic block header. Five bits of HLIT, five of
|
|
|
+ * HDIST, four of HCLEN.
|
|
|
+ */
|
|
|
+ if (dctx->nbits < 5 + 5 + 4)
|
|
|
+ goto finished; /* done all we can */
|
|
|
+ dctx->hlit = 257 + (dctx->bits & 31);
|
|
|
+ EATBITS(5);
|
|
|
+ dctx->hdist = 1 + (dctx->bits & 31);
|
|
|
+ EATBITS(5);
|
|
|
+ dctx->hclen = 4 + (dctx->bits & 15);
|
|
|
+ EATBITS(4);
|
|
|
+ dctx->lenptr = 0;
|
|
|
+ dctx->state = TREES_LENLEN;
|
|
|
+ memset(dctx->lenlen, 0, sizeof(dctx->lenlen));
|
|
|
+ break;
|
|
|
+ case TREES_LENLEN:
|
|
|
+ if (dctx->nbits < 3)
|
|
|
+ goto finished;
|
|
|
+ while (dctx->lenptr < dctx->hclen && dctx->nbits >= 3) {
|
|
|
+ dctx->lenlen[lenlenmap[dctx->lenptr++]] =
|
|
|
+ (unsigned char) (dctx->bits & 7);
|
|
|
+ EATBITS(3);
|
|
|
+ }
|
|
|
+ if (dctx->lenptr == dctx->hclen) {
|
|
|
+ dctx->lenlentable = zlib_mktable(dctx->lenlen, 19);
|
|
|
+ dctx->state = TREES_LEN;
|
|
|
+ dctx->lenptr = 0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case TREES_LEN:
|
|
|
+ if (dctx->lenptr >= dctx->hlit + dctx->hdist) {
|
|
|
+ dctx->currlentable = zlib_mktable(dctx->lengths, dctx->hlit);
|
|
|
+ dctx->currdisttable = zlib_mktable(dctx->lengths + dctx->hlit,
|
|
|
+ dctx->hdist);
|
|
|
+ zlib_freetable(&dctx->lenlentable);
|
|
|
+ dctx->lenlentable = NULL;
|
|
|
+ dctx->state = INBLK;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ code =
|
|
|
+ zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->lenlentable);
|
|
|
+ if (code == -1)
|
|
|
+ goto finished;
|
|
|
+ if (code == -2)
|
|
|
+ goto decode_error;
|
|
|
+ if (code < 16)
|
|
|
+ dctx->lengths[dctx->lenptr++] = code;
|
|
|
+ else {
|
|
|
+ dctx->lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
|
|
+ dctx->lenaddon = (code == 18 ? 11 : 3);
|
|
|
+ dctx->lenrep = (code == 16 && dctx->lenptr > 0 ?
|
|
|
+ dctx->lengths[dctx->lenptr - 1] : 0);
|
|
|
+ dctx->state = TREES_LENREP;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case TREES_LENREP:
|
|
|
+ if (dctx->nbits < dctx->lenextrabits)
|
|
|
+ goto finished;
|
|
|
+ rep =
|
|
|
+ dctx->lenaddon +
|
|
|
+ (dctx->bits & ((1 << dctx->lenextrabits) - 1));
|
|
|
+ EATBITS(dctx->lenextrabits);
|
|
|
+ while (rep > 0 && dctx->lenptr < dctx->hlit + dctx->hdist) {
|
|
|
+ dctx->lengths[dctx->lenptr] = dctx->lenrep;
|
|
|
+ dctx->lenptr++;
|
|
|
+ rep--;
|
|
|
+ }
|
|
|
+ dctx->state = TREES_LEN;
|
|
|
+ break;
|
|
|
+ case INBLK:
|
|
|
+ code =
|
|
|
+ zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->currlentable);
|
|
|
+ if (code == -1)
|
|
|
+ goto finished;
|
|
|
+ if (code == -2)
|
|
|
+ goto decode_error;
|
|
|
+ if (code < 256)
|
|
|
+ zlib_emit_char(dctx, code);
|
|
|
+ else if (code == 256) {
|
|
|
+ dctx->state = OUTSIDEBLK;
|
|
|
+ if (dctx->currlentable != dctx->staticlentable) {
|
|
|
+ zlib_freetable(&dctx->currlentable);
|
|
|
+ dctx->currlentable = NULL;
|
|
|
+ }
|
|
|
+ if (dctx->currdisttable != dctx->staticdisttable) {
|
|
|
+ zlib_freetable(&dctx->currdisttable);
|
|
|
+ dctx->currdisttable = NULL;
|
|
|
+ }
|
|
|
+ } else if (code < 286) {
|
|
|
+ dctx->state = GOTLENSYM;
|
|
|
+ dctx->sym = code;
|
|
|
+ } else {
|
|
|
/* literal/length symbols 286 and 287 are invalid */
|
|
|
goto decode_error;
|
|
|
}
|
|
|
- break;
|
|
|
- case GOTLENSYM:
|
|
|
- rec = &lencodes[dctx->sym - 257];
|
|
|
- if (dctx->nbits < rec->extrabits)
|
|
|
- goto finished;
|
|
|
- dctx->len =
|
|
|
- rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
|
|
- EATBITS(rec->extrabits);
|
|
|
- dctx->state = GOTLEN;
|
|
|
- break;
|
|
|
- case GOTLEN:
|
|
|
- code =
|
|
|
- zlib_huflookup(&dctx->bits, &dctx->nbits,
|
|
|
- dctx->currdisttable);
|
|
|
- if (code == -1)
|
|
|
- goto finished;
|
|
|
- if (code == -2)
|
|
|
- goto decode_error;
|
|
|
- if (code >= 30) /* dist symbols 30 and 31 are invalid */
|
|
|
- goto decode_error;
|
|
|
- dctx->state = GOTDISTSYM;
|
|
|
- dctx->sym = code;
|
|
|
- break;
|
|
|
- case GOTDISTSYM:
|
|
|
- rec = &distcodes[dctx->sym];
|
|
|
- if (dctx->nbits < rec->extrabits)
|
|
|
- goto finished;
|
|
|
- dist = rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
|
|
- EATBITS(rec->extrabits);
|
|
|
- dctx->state = INBLK;
|
|
|
- while (dctx->len--)
|
|
|
- zlib_emit_char(dctx, dctx->window[(dctx->winpos - dist) &
|
|
|
- (WINSIZE - 1)]);
|
|
|
- break;
|
|
|
- case UNCOMP_LEN:
|
|
|
- /*
|
|
|
- * Uncompressed block. We expect to see a 16-bit LEN.
|
|
|
- */
|
|
|
- if (dctx->nbits < 16)
|
|
|
- goto finished;
|
|
|
- dctx->uncomplen = dctx->bits & 0xFFFF;
|
|
|
- EATBITS(16);
|
|
|
- dctx->state = UNCOMP_NLEN;
|
|
|
- break;
|
|
|
- case UNCOMP_NLEN:
|
|
|
- /*
|
|
|
- * Uncompressed block. We expect to see a 16-bit NLEN,
|
|
|
- * which should be the one's complement of the previous
|
|
|
- * LEN.
|
|
|
- */
|
|
|
- if (dctx->nbits < 16)
|
|
|
- goto finished;
|
|
|
- nlen = dctx->bits & 0xFFFF;
|
|
|
- EATBITS(16);
|
|
|
- if (dctx->uncomplen != (nlen ^ 0xFFFF))
|
|
|
- goto decode_error;
|
|
|
- if (dctx->uncomplen == 0)
|
|
|
- dctx->state = OUTSIDEBLK; /* block is empty */
|
|
|
- else
|
|
|
- dctx->state = UNCOMP_DATA;
|
|
|
- break;
|
|
|
- case UNCOMP_DATA:
|
|
|
- if (dctx->nbits < 8)
|
|
|
- goto finished;
|
|
|
- zlib_emit_char(dctx, dctx->bits & 0xFF);
|
|
|
- EATBITS(8);
|
|
|
- if (--dctx->uncomplen == 0)
|
|
|
- dctx->state = OUTSIDEBLK; /* end of uncompressed block */
|
|
|
- break;
|
|
|
- }
|
|
|
+ break;
|
|
|
+ case GOTLENSYM:
|
|
|
+ rec = &lencodes[dctx->sym - 257];
|
|
|
+ if (dctx->nbits < rec->extrabits)
|
|
|
+ goto finished;
|
|
|
+ dctx->len =
|
|
|
+ rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
|
|
+ EATBITS(rec->extrabits);
|
|
|
+ dctx->state = GOTLEN;
|
|
|
+ break;
|
|
|
+ case GOTLEN:
|
|
|
+ code =
|
|
|
+ zlib_huflookup(&dctx->bits, &dctx->nbits,
|
|
|
+ dctx->currdisttable);
|
|
|
+ if (code == -1)
|
|
|
+ goto finished;
|
|
|
+ if (code == -2)
|
|
|
+ goto decode_error;
|
|
|
+ if (code >= 30) /* dist symbols 30 and 31 are invalid */
|
|
|
+ goto decode_error;
|
|
|
+ dctx->state = GOTDISTSYM;
|
|
|
+ dctx->sym = code;
|
|
|
+ break;
|
|
|
+ case GOTDISTSYM:
|
|
|
+ rec = &distcodes[dctx->sym];
|
|
|
+ if (dctx->nbits < rec->extrabits)
|
|
|
+ goto finished;
|
|
|
+ dist = rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
|
|
+ EATBITS(rec->extrabits);
|
|
|
+ dctx->state = INBLK;
|
|
|
+ while (dctx->len--)
|
|
|
+ zlib_emit_char(dctx, dctx->window[(dctx->winpos - dist) &
|
|
|
+ (WINSIZE - 1)]);
|
|
|
+ break;
|
|
|
+ case UNCOMP_LEN:
|
|
|
+ /*
|
|
|
+ * Uncompressed block. We expect to see a 16-bit LEN.
|
|
|
+ */
|
|
|
+ if (dctx->nbits < 16)
|
|
|
+ goto finished;
|
|
|
+ dctx->uncomplen = dctx->bits & 0xFFFF;
|
|
|
+ EATBITS(16);
|
|
|
+ dctx->state = UNCOMP_NLEN;
|
|
|
+ break;
|
|
|
+ case UNCOMP_NLEN:
|
|
|
+ /*
|
|
|
+ * Uncompressed block. We expect to see a 16-bit NLEN,
|
|
|
+ * which should be the one's complement of the previous
|
|
|
+ * LEN.
|
|
|
+ */
|
|
|
+ if (dctx->nbits < 16)
|
|
|
+ goto finished;
|
|
|
+ nlen = dctx->bits & 0xFFFF;
|
|
|
+ EATBITS(16);
|
|
|
+ if (dctx->uncomplen != (nlen ^ 0xFFFF))
|
|
|
+ goto decode_error;
|
|
|
+ if (dctx->uncomplen == 0)
|
|
|
+ dctx->state = OUTSIDEBLK; /* block is empty */
|
|
|
+ else
|
|
|
+ dctx->state = UNCOMP_DATA;
|
|
|
+ break;
|
|
|
+ case UNCOMP_DATA:
|
|
|
+ if (dctx->nbits < 8)
|
|
|
+ goto finished;
|
|
|
+ zlib_emit_char(dctx, dctx->bits & 0xFF);
|
|
|
+ EATBITS(8);
|
|
|
+ if (--dctx->uncomplen == 0)
|
|
|
+ dctx->state = OUTSIDEBLK; /* end of uncompressed block */
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
finished:
|