- 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);
- /* FIXME: zlib_freetable(dctx.lenlentable); */
- dctx.state = INBLK;
- break;
- }
- code = zlib_huflookup(&dctx.bits, &dctx.nbits, dctx.lenlentable);
- if (code == -1)
- goto finished;
- 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 < 256)
- zlib_emit_char(code);
- else if (code == 256) {
- dctx.state = OUTSIDEBLK;
- /* FIXME: zlib_freetable(both) if not static */
- } else if (code < 286) { /* static tree can give >285; ignore */
- dctx.state = GOTLENSYM;
- dctx.sym = code;
- }
- 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;
- 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.window[(dctx.winpos-dist) & (WINSIZE-1)]);
+ if ((header & 0x0F00) != 0x0800 ||
+ (header & 0xF000) > 0x7000 ||
+ (header & 0x0020) != 0x0000 ||
+ (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) { /* static tree can give >285; ignore */
+ dctx->state = GOTLENSYM;
+ dctx->sym = code;
+ }
+ 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;
+ 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)]);