#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
#ifdef MAKEFIXED
# ifndef BUILDFIXED
# define BUILDFIXED
# endif
#endif
local
int
inflateStateCheck(z_streamp strm) {
struct
inflate_state FAR *state;
if
(strm == Z_NULL ||
strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
return
1;
state = (
struct
inflate_state FAR *)strm->state;
if
(state == Z_NULL || state->strm != strm ||
state->mode < HEAD || state->mode > SYNC)
return
1;
return
0;
}
int
ZEXPORT inflateResetKeep(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
strm->total_in = strm->total_out = state->total = 0;
strm->msg = Z_NULL;
if
(state->wrap)
strm->adler = state->wrap & 1;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
state->flags = -1;
state->dmax = 32768U;
state->head = Z_NULL;
state->hold = 0;
state->bits = 0;
state->lencode = state->distcode = state->next = state->codes;
state->sane = 1;
state->back = -1;
Tracev((stderr,
"inflate: reset\n"
));
return
Z_OK;
}
int
ZEXPORT inflateReset(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
state->wsize = 0;
state->whave = 0;
state->wnext = 0;
return
inflateResetKeep(strm);
}
int
ZEXPORT inflateReset2(z_streamp strm,
int
windowBits) {
int
wrap;
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(windowBits < 0) {
if
(windowBits < -15)
return
Z_STREAM_ERROR;
wrap = 0;
windowBits = -windowBits;
}
else
{
wrap = (windowBits >> 4) + 5;
#ifdef GUNZIP
if
(windowBits < 48)
windowBits &= 15;
#endif
}
if
(windowBits && (windowBits < 8 || windowBits > 15))
return
Z_STREAM_ERROR;
if
(state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
ZFREE(strm, state->window);
state->window = Z_NULL;
}
state->wrap = wrap;
state->wbits = (unsigned)windowBits;
return
inflateReset(strm);
}
int
ZEXPORT inflateInit2_(z_streamp strm,
int
windowBits,
const
char
*version,
int
stream_size) {
int
ret;
struct
inflate_state FAR *state;
if
(version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (
int
)(
sizeof
(z_stream)))
return
Z_VERSION_ERROR;
if
(strm == Z_NULL)
return
Z_STREAM_ERROR;
strm->msg = Z_NULL;
if
(strm->zalloc == (alloc_func)0) {
#ifdef Z_SOLO
return
Z_STREAM_ERROR;
#else
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
#endif
}
if
(strm->zfree == (free_func)0)
#ifdef Z_SOLO
return
Z_STREAM_ERROR;
#else
strm->zfree = zcfree;
#endif
state = (
struct
inflate_state FAR *)
ZALLOC(strm, 1,
sizeof
(
struct
inflate_state));
if
(state == Z_NULL)
return
Z_MEM_ERROR;
Tracev((stderr,
"inflate: allocated\n"
));
strm->state = (
struct
internal_state FAR *)state;
state->strm = strm;
state->window = Z_NULL;
state->mode = HEAD;
ret = inflateReset2(strm, windowBits);
if
(ret != Z_OK) {
ZFREE(strm, state);
strm->state = Z_NULL;
}
return
ret;
}
int
ZEXPORT inflateInit_(z_streamp strm,
const
char
*version,
int
stream_size) {
return
inflateInit2_(strm, DEF_WBITS, version, stream_size);
}
int
ZEXPORT inflatePrime(z_streamp strm,
int
bits,
int
value) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
if
(bits == 0)
return
Z_OK;
state = (
struct
inflate_state FAR *)strm->state;
if
(bits < 0) {
state->hold = 0;
state->bits = 0;
return
Z_OK;
}
if
(bits > 16 || state->bits + (uInt)bits > 32)
return
Z_STREAM_ERROR;
value &= (1L << bits) - 1;
state->hold += (unsigned)value << state->bits;
state->bits += (uInt)bits;
return
Z_OK;
}
local
void
fixedtables(
struct
inflate_state FAR *state) {
#ifdef BUILDFIXED
static
int
virgin = 1;
static
code *lenfix, *distfix;
static
code fixed[544];
if
(virgin) {
unsigned sym, bits;
static
code *next;
sym = 0;
while
(sym < 144) state->lens[sym++] = 8;
while
(sym < 256) state->lens[sym++] = 9;
while
(sym < 280) state->lens[sym++] = 7;
while
(sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
sym = 0;
while
(sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
virgin = 0;
}
#else /* !BUILDFIXED */
# include "inffixed.h"
#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}
#ifdef MAKEFIXED
#include <stdio.h>
void
makefixed(
void
)
{
unsigned low, size;
struct
inflate_state state;
fixedtables(&state);
puts
(
" /* inffixed.h -- table for decoding fixed codes"
);
puts
(
" * Generated automatically by makefixed()."
);
puts
(
" */"
);
puts
(
""
);
puts
(
" /* WARNING: this file should *not* be used by applications."
);
puts
(
" It is part of the implementation of this library and is"
);
puts
(
" subject to change. Applications should only use zlib.h."
);
puts
(
" */"
);
puts
(
""
);
size = 1U << 9;
printf
(
" static const code lenfix[%u] = {"
, size);
low = 0;
for
(;;) {
if
((low % 7) == 0)
printf
(
"\n "
);
printf
(
"{%u,%u,%d}"
, (low & 127) == 99 ? 64 : state.lencode[low].op,
state.lencode[low].bits, state.lencode[low].val);
if
(++low == size)
break
;
putchar
(
','
);
}
puts
(
"\n };"
);
size = 1U << 5;
printf
(
"\n static const code distfix[%u] = {"
, size);
low = 0;
for
(;;) {
if
((low % 6) == 0)
printf
(
"\n "
);
printf
(
"{%u,%u,%d}"
, state.distcode[low].op, state.distcode[low].bits,
state.distcode[low].val);
if
(++low == size)
break
;
putchar
(
','
);
}
puts
(
"\n };"
);
}
#endif /* MAKEFIXED */
local
int
updatewindow(z_streamp strm,
const
Bytef *end, unsigned copy) {
struct
inflate_state FAR *state;
unsigned dist;
state = (
struct
inflate_state FAR *)strm->state;
if
(state->window == Z_NULL) {
state->window = (unsigned
char
FAR *)
ZALLOC(strm, 1U << state->wbits,
sizeof
(unsigned
char
));
if
(state->window == Z_NULL)
return
1;
}
if
(state->wsize == 0) {
state->wsize = 1U << state->wbits;
state->wnext = 0;
state->whave = 0;
}
if
(copy >= state->wsize) {
zmemcpy(state->window, end - state->wsize, state->wsize);
state->wnext = 0;
state->whave = state->wsize;
}
else
{
dist = state->wsize - state->wnext;
if
(dist > copy) dist = copy;
zmemcpy(state->window + state->wnext, end - copy, dist);
copy -= dist;
if
(copy) {
zmemcpy(state->window, end - copy, copy);
state->wnext = copy;
state->whave = state->wsize;
}
else
{
state->wnext += dist;
if
(state->wnext == state->wsize) state->wnext = 0;
if
(state->whave < state->wsize) state->whave += dist;
}
}
return
0;
}
#ifdef GUNZIP
# define UPDATE_CHECK(check, buf, len) \
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif
#ifdef GUNZIP
# define CRC2(check, word) \
do
{ \
hbuf[0] = (unsigned
char
)(word); \
hbuf[1] = (unsigned
char
)((word) >> 8); \
check = crc32(check, hbuf, 2); \
}
while
(0)
# define CRC4(check, word) \
do
{ \
hbuf[0] = (unsigned
char
)(word); \
hbuf[1] = (unsigned
char
)((word) >> 8); \
hbuf[2] = (unsigned
char
)((word) >> 16); \
hbuf[3] = (unsigned
char
)((word) >> 24); \
check = crc32(check, hbuf, 4); \
}
while
(0)
#endif
#define LOAD() \
do
{ \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
}
while
(0)
#define RESTORE() \
do
{ \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
}
while
(0)
#define INITBITS() \
do
{ \
hold = 0; \
bits = 0; \
}
while
(0)
#define PULLBYTE() \
do
{ \
if
(have == 0)
goto
inf_leave; \
have--; \
hold += (unsigned
long
)(*next++) << bits; \
bits += 8; \
}
while
(0)
#define NEEDBITS(n) \
do
{ \
while
(bits < (unsigned)(n)) \
PULLBYTE(); \
}
while
(0)
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))
#define DROPBITS(n) \
do
{ \
hold >>= (n); \
bits -= (unsigned)(n); \
}
while
(0)
#define BYTEBITS() \
do
{ \
hold >>= bits & 7; \
bits -= bits & 7; \
}
while
(0)
int
ZEXPORT inflate(z_streamp strm,
int
flush) {
struct
inflate_state FAR *state;
z_const unsigned
char
FAR *next;
unsigned
char
FAR *put;
unsigned have, left;
unsigned
long
hold;
unsigned bits;
unsigned in, out;
unsigned copy;
unsigned
char
FAR *from;
code here;
code last;
unsigned len;
int
ret;
#ifdef GUNZIP
unsigned
char
hbuf[4];
#endif
static
const
unsigned
short
order[19] =
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
if
(inflateStateCheck(strm) || strm->next_out == Z_NULL ||
(strm->next_in == Z_NULL && strm->avail_in != 0))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(state->mode == TYPE) state->mode = TYPEDO;
LOAD();
in = have;
out = left;
ret = Z_OK;
for
(;;)
switch
(state->mode) {
case
HEAD:
if
(state->wrap == 0) {
state->mode = TYPEDO;
break
;
}
NEEDBITS(16);
#ifdef GUNZIP
if
((state->wrap & 2) && hold == 0x8b1f) {
if
(state->wbits == 0)
state->wbits = 15;
state->check = crc32(0L, Z_NULL, 0);
CRC2(state->check, hold);
INITBITS();
state->mode = FLAGS;
break
;
}
if
(state->head != Z_NULL)
state->head->done = -1;
if
(!(state->wrap & 1) ||
#else
if
(
#endif
((BITS(8) << 8) + (hold >> 8)) % 31) {
strm->msg = (
char
*)
"incorrect header check"
;
state->mode = BAD;
break
;
}
if
(BITS(4) != Z_DEFLATED) {
strm->msg = (
char
*)
"unknown compression method"
;
state->mode = BAD;
break
;
}
DROPBITS(4);
len = BITS(4) + 8;
if
(state->wbits == 0)
state->wbits = len;
if
(len > 15 || len > state->wbits) {
strm->msg = (
char
*)
"invalid window size"
;
state->mode = BAD;
break
;
}
state->dmax = 1U << len;
state->flags = 0;
Tracev((stderr,
"inflate: zlib header ok\n"
));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
INITBITS();
break
;
#ifdef GUNZIP
case
FLAGS:
NEEDBITS(16);
state->flags = (
int
)(hold);
if
((state->flags & 0xff) != Z_DEFLATED) {
strm->msg = (
char
*)
"unknown compression method"
;
state->mode = BAD;
break
;
}
if
(state->flags & 0xe000) {
strm->msg = (
char
*)
"unknown header flags set"
;
state->mode = BAD;
break
;
}
if
(state->head != Z_NULL)
state->head->text = (
int
)((hold >> 8) & 1);
if
((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
case
TIME:
NEEDBITS(32);
if
(state->head != Z_NULL)
state->head->
time
= hold;
if
((state->flags & 0x0200) && (state->wrap & 4))
CRC4(state->check, hold);
INITBITS();
state->mode = OS;
case
OS:
NEEDBITS(16);
if
(state->head != Z_NULL) {
state->head->xflags = (
int
)(hold & 0xff);
state->head->os = (
int
)(hold >> 8);
}
if
((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
case
EXLEN:
if
(state->flags & 0x0400) {
NEEDBITS(16);
state->length = (unsigned)(hold);
if
(state->head != Z_NULL)
state->head->extra_len = (unsigned)hold;
if
((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
}
else
if
(state->head != Z_NULL)
state->head->extra = Z_NULL;
state->mode = EXTRA;
case
EXTRA:
if
(state->flags & 0x0400) {
copy = state->length;
if
(copy > have) copy = have;
if
(copy) {
if
(state->head != Z_NULL &&
state->head->extra != Z_NULL &&
(len = state->head->extra_len - state->length) <
state->head->extra_max) {
zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);
}
if
((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
state->length -= copy;
}
if
(state->length)
goto
inf_leave;
}
state->length = 0;
state->mode = NAME;
case
NAME:
if
(state->flags & 0x0800) {
if
(have == 0)
goto
inf_leave;
copy = 0;
do
{
len = (unsigned)(next[copy++]);
if
(state->head != Z_NULL &&
state->head->name != Z_NULL &&
state->length < state->head->name_max)
state->head->name[state->length++] = (Bytef)len;
}
while
(len && copy < have);
if
((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
if
(len)
goto
inf_leave;
}
else
if
(state->head != Z_NULL)
state->head->name = Z_NULL;
state->length = 0;
state->mode = COMMENT;
case
COMMENT:
if
(state->flags & 0x1000) {
if
(have == 0)
goto
inf_leave;
copy = 0;
do
{
len = (unsigned)(next[copy++]);
if
(state->head != Z_NULL &&
state->head->comment != Z_NULL &&
state->length < state->head->comm_max)
state->head->comment[state->length++] = (Bytef)len;
}
while
(len && copy < have);
if
((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
if
(len)
goto
inf_leave;
}
else
if
(state->head != Z_NULL)
state->head->comment = Z_NULL;
state->mode = HCRC;
case
HCRC:
if
(state->flags & 0x0200) {
NEEDBITS(16);
if
((state->wrap & 4) && hold != (state->check & 0xffff)) {
strm->msg = (
char
*)
"header crc mismatch"
;
state->mode = BAD;
break
;
}
INITBITS();
}
if
(state->head != Z_NULL) {
state->head->hcrc = (
int
)((state->flags >> 9) & 1);
state->head->done = 1;
}
strm->adler = state->check = crc32(0L, Z_NULL, 0);
state->mode = TYPE;
break
;
#endif
case
DICTID:
NEEDBITS(32);
strm->adler = state->check = ZSWAP32(hold);
INITBITS();
state->mode = DICT;
case
DICT:
if
(state->havedict == 0) {
RESTORE();
return
Z_NEED_DICT;
}
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE;
case
TYPE:
if
(flush == Z_BLOCK || flush == Z_TREES)
goto
inf_leave;
case
TYPEDO:
if
(state->last) {
BYTEBITS();
state->mode = CHECK;
break
;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch
(BITS(2)) {
case
0:
Tracev((stderr,
"inflate: stored block%s\n"
,
state->last ?
" (last)"
:
""
));
state->mode = STORED;
break
;
case
1:
fixedtables(state);
Tracev((stderr,
"inflate: fixed codes block%s\n"
,
state->last ?
" (last)"
:
""
));
state->mode = LEN_;
if
(flush == Z_TREES) {
DROPBITS(2);
goto
inf_leave;
}
break
;
case
2:
Tracev((stderr,
"inflate: dynamic codes block%s\n"
,
state->last ?
" (last)"
:
""
));
state->mode = TABLE;
break
;
case
3:
strm->msg = (
char
*)
"invalid block type"
;
state->mode = BAD;
}
DROPBITS(2);
break
;
case
STORED:
BYTEBITS();
NEEDBITS(32);
if
((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (
char
*)
"invalid stored block lengths"
;
state->mode = BAD;
break
;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr,
"inflate: stored length %u\n"
,
state->length));
INITBITS();
state->mode = COPY_;
if
(flush == Z_TREES)
goto
inf_leave;
case
COPY_:
state->mode = COPY;
case
COPY:
copy = state->length;
if
(copy) {
if
(copy > have) copy = have;
if
(copy > left) copy = left;
if
(copy == 0)
goto
inf_leave;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
break
;
}
Tracev((stderr,
"inflate: stored end\n"
));
state->mode = TYPE;
break
;
case
TABLE:
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if
(state->nlen > 286 || state->ndist > 30) {
strm->msg = (
char
*)
"too many length or distance symbols"
;
state->mode = BAD;
break
;
}
#endif
Tracev((stderr,
"inflate: table sizes ok\n"
));
state->have = 0;
state->mode = LENLENS;
case
LENLENS:
while
(state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned
short
)BITS(3);
DROPBITS(3);
}
while
(state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (
const
code FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if
(ret) {
strm->msg = (
char
*)
"invalid code lengths set"
;
state->mode = BAD;
break
;
}
Tracev((stderr,
"inflate: code lengths ok\n"
));
state->have = 0;
state->mode = CODELENS;
case
CODELENS:
while
(state->have < state->nlen + state->ndist) {
for
(;;) {
here = state->lencode[BITS(state->lenbits)];
if
((unsigned)(here.bits) <= bits)
break
;
PULLBYTE();
}
if
(here.val < 16) {
DROPBITS(here.bits);
state->lens[state->have++] = here.val;
}
else
{
if
(here.val == 16) {
NEEDBITS(here.bits + 2);
DROPBITS(here.bits);
if
(state->have == 0) {
strm->msg = (
char
*)
"invalid bit length repeat"
;
state->mode = BAD;
break
;
}
len = state->lens[state->have - 1];
copy = 3 + BITS(2);
DROPBITS(2);
}
else
if
(here.val == 17) {
NEEDBITS(here.bits + 3);
DROPBITS(here.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else
{
NEEDBITS(here.bits + 7);
DROPBITS(here.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if
(state->have + copy > state->nlen + state->ndist) {
strm->msg = (
char
*)
"invalid bit length repeat"
;
state->mode = BAD;
break
;
}
while
(copy--)
state->lens[state->have++] = (unsigned
short
)len;
}
}
if
(state->mode == BAD)
break
;
if
(state->lens[256] == 0) {
strm->msg = (
char
*)
"invalid code -- missing end-of-block"
;
state->mode = BAD;
break
;
}
state->next = state->codes;
state->lencode = (
const
code FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if
(ret) {
strm->msg = (
char
*)
"invalid literal/lengths set"
;
state->mode = BAD;
break
;
}
state->distcode = (
const
code FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if
(ret) {
strm->msg = (
char
*)
"invalid distances set"
;
state->mode = BAD;
break
;
}
Tracev((stderr,
"inflate: codes ok\n"
));
state->mode = LEN_;
if
(flush == Z_TREES)
goto
inf_leave;
case
LEN_:
state->mode = LEN;
case
LEN:
if
(have >= 6 && left >= 258) {
RESTORE();
inflate_fast(strm, out);
LOAD();
if
(state->mode == TYPE)
state->back = -1;
break
;
}
state->back = 0;
for
(;;) {
here = state->lencode[BITS(state->lenbits)];
if
((unsigned)(here.bits) <= bits)
break
;
PULLBYTE();
}
if
(here.op && (here.op & 0xf0) == 0) {
last = here;
for
(;;) {
here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if
((unsigned)(last.bits + here.bits) <= bits)
break
;
PULLBYTE();
}
DROPBITS(last.bits);
state->back += last.bits;
}
DROPBITS(here.bits);
state->back += here.bits;
state->length = (unsigned)here.val;
if
((
int
)(here.op) == 0) {
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n"
:
"inflate: literal 0x%02x\n"
, here.val));
state->mode = LIT;
break
;
}
if
(here.op & 32) {
Tracevv((stderr,
"inflate: end of block\n"
));
state->back = -1;
state->mode = TYPE;
break
;
}
if
(here.op & 64) {
strm->msg = (
char
*)
"invalid literal/length code"
;
state->mode = BAD;
break
;
}
state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT;
case
LENEXT:
if
(state->extra) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
state->back += state->extra;
}
Tracevv((stderr,
"inflate: length %u\n"
, state->length));
state->was = state->length;
state->mode = DIST;
case
DIST:
for
(;;) {
here = state->distcode[BITS(state->distbits)];
if
((unsigned)(here.bits) <= bits)
break
;
PULLBYTE();
}
if
((here.op & 0xf0) == 0) {
last = here;
for
(;;) {
here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if
((unsigned)(last.bits + here.bits) <= bits)
break
;
PULLBYTE();
}
DROPBITS(last.bits);
state->back += last.bits;
}
DROPBITS(here.bits);
state->back += here.bits;
if
(here.op & 64) {
strm->msg = (
char
*)
"invalid distance code"
;
state->mode = BAD;
break
;
}
state->offset = (unsigned)here.val;
state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT;
case
DISTEXT:
if
(state->extra) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
state->back += state->extra;
}
#ifdef INFLATE_STRICT
if
(state->offset > state->dmax) {
strm->msg = (
char
*)
"invalid distance too far back"
;
state->mode = BAD;
break
;
}
#endif
Tracevv((stderr,
"inflate: distance %u\n"
, state->offset));
state->mode = MATCH;
case
MATCH:
if
(left == 0)
goto
inf_leave;
copy = out - left;
if
(state->offset > copy) {
copy = state->offset - copy;
if
(copy > state->whave) {
if
(state->sane) {
strm->msg = (
char
*)
"invalid distance too far back"
;
state->mode = BAD;
break
;
}
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
Trace((stderr,
"inflate.c too far\n"
));
copy -= state->whave;
if
(copy > state->length) copy = state->length;
if
(copy > left) copy = left;
left -= copy;
state->length -= copy;
do
{
*put++ = 0;
}
while
(--copy);
if
(state->length == 0) state->mode = LEN;
break
;
#endif
}
if
(copy > state->wnext) {
copy -= state->wnext;
from = state->window + (state->wsize - copy);
}
else
from = state->window + (state->wnext - copy);
if
(copy > state->length) copy = state->length;
}
else
{
from = put - state->offset;
copy = state->length;
}
if
(copy > left) copy = left;
left -= copy;
state->length -= copy;
do
{
*put++ = *from++;
}
while
(--copy);
if
(state->length == 0) state->mode = LEN;
break
;
case
LIT:
if
(left == 0)
goto
inf_leave;
*put++ = (unsigned
char
)(state->length);
left--;
state->mode = LEN;
break
;
case
CHECK:
if
(state->wrap) {
NEEDBITS(32);
out -= left;
strm->total_out += out;
state->total += out;
if
((state->wrap & 4) && out)
strm->adler = state->check =
UPDATE_CHECK(state->check, put - out, out);
out = left;
if
((state->wrap & 4) && (
#ifdef GUNZIP
state->flags ? hold :
#endif
ZSWAP32(hold)) != state->check) {
strm->msg = (
char
*)
"incorrect data check"
;
state->mode = BAD;
break
;
}
INITBITS();
Tracev((stderr,
"inflate: check matches trailer\n"
));
}
#ifdef GUNZIP
state->mode = LENGTH;
case
LENGTH:
if
(state->wrap && state->flags) {
NEEDBITS(32);
if
((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
strm->msg = (
char
*)
"incorrect length check"
;
state->mode = BAD;
break
;
}
INITBITS();
Tracev((stderr,
"inflate: length matches trailer\n"
));
}
#endif
state->mode = DONE;
case
DONE:
ret = Z_STREAM_END;
goto
inf_leave;
case
BAD:
ret = Z_DATA_ERROR;
goto
inf_leave;
case
MEM:
return
Z_MEM_ERROR;
case
SYNC:
default
:
return
Z_STREAM_ERROR;
}
inf_leave:
RESTORE();
if
(state->wsize || (out != strm->avail_out && state->mode < BAD &&
(state->mode < CHECK || flush != Z_FINISH)))
if
(updatewindow(strm, strm->next_out, out - strm->avail_out)) {
state->mode = MEM;
return
Z_MEM_ERROR;
}
in -= strm->avail_in;
out -= strm->avail_out;
strm->total_in += in;
strm->total_out += out;
state->total += out;
if
((state->wrap & 4) && out)
strm->adler = state->check =
UPDATE_CHECK(state->check, strm->next_out - out, out);
strm->data_type = (
int
)state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
if
(((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
ret = Z_BUF_ERROR;
return
ret;
}
int
ZEXPORT inflateEnd(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(state->window != Z_NULL) ZFREE(strm, state->window);
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr,
"inflate: end\n"
));
return
Z_OK;
}
int
ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
uInt *dictLength) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(state->whave && dictionary != Z_NULL) {
zmemcpy(dictionary, state->window + state->wnext,
state->whave - state->wnext);
zmemcpy(dictionary + state->whave - state->wnext,
state->window, state->wnext);
}
if
(dictLength != Z_NULL)
*dictLength = state->whave;
return
Z_OK;
}
int
ZEXPORT inflateSetDictionary(z_streamp strm,
const
Bytef *dictionary,
uInt dictLength) {
struct
inflate_state FAR *state;
unsigned
long
dictid;
int
ret;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(state->wrap != 0 && state->mode != DICT)
return
Z_STREAM_ERROR;
if
(state->mode == DICT) {
dictid = adler32(0L, Z_NULL, 0);
dictid = adler32(dictid, dictionary, dictLength);
if
(dictid != state->check)
return
Z_DATA_ERROR;
}
ret = updatewindow(strm, dictionary + dictLength, dictLength);
if
(ret) {
state->mode = MEM;
return
Z_MEM_ERROR;
}
state->havedict = 1;
Tracev((stderr,
"inflate: dictionary set\n"
));
return
Z_OK;
}
int
ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
((state->wrap & 2) == 0)
return
Z_STREAM_ERROR;
state->head = head;
head->done = 0;
return
Z_OK;
}
local unsigned syncsearch(unsigned FAR *have,
const
unsigned
char
FAR *buf,
unsigned len) {
unsigned got;
unsigned next;
got = *have;
next = 0;
while
(next < len && got < 4) {
if
((
int
)(buf[next]) == (got < 2 ? 0 : 0xff))
got++;
else
if
(buf[next])
got = 0;
else
got = 4 - got;
next++;
}
*have = got;
return
next;
}
int
ZEXPORT inflateSync(z_streamp strm) {
unsigned len;
int
flags;
unsigned
long
in, out;
unsigned
char
buf[4];
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(strm->avail_in == 0 && state->bits < 8)
return
Z_BUF_ERROR;
if
(state->mode != SYNC) {
state->mode = SYNC;
state->hold >>= state->bits & 7;
state->bits -= state->bits & 7;
len = 0;
while
(state->bits >= 8) {
buf[len++] = (unsigned
char
)(state->hold);
state->hold >>= 8;
state->bits -= 8;
}
state->have = 0;
syncsearch(&(state->have), buf, len);
}
len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
strm->avail_in -= len;
strm->next_in += len;
strm->total_in += len;
if
(state->have != 4)
return
Z_DATA_ERROR;
if
(state->flags == -1)
state->wrap = 0;
else
state->wrap &= ~4;
flags = state->flags;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
state->flags = flags;
state->mode = TYPE;
return
Z_OK;
}
int
ZEXPORT inflateSyncPoint(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
return
state->mode == STORED && state->bits == 0;
}
int
ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
struct
inflate_state FAR *state;
struct
inflate_state FAR *copy;
unsigned
char
FAR *window;
unsigned wsize;
if
(inflateStateCheck(source) || dest == Z_NULL)
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)source->state;
copy = (
struct
inflate_state FAR *)
ZALLOC(source, 1,
sizeof
(
struct
inflate_state));
if
(copy == Z_NULL)
return
Z_MEM_ERROR;
window = Z_NULL;
if
(state->window != Z_NULL) {
window = (unsigned
char
FAR *)
ZALLOC(source, 1U << state->wbits,
sizeof
(unsigned
char
));
if
(window == Z_NULL) {
ZFREE(source, copy);
return
Z_MEM_ERROR;
}
}
zmemcpy((voidpf)dest, (voidpf)source,
sizeof
(z_stream));
zmemcpy((voidpf)copy, (voidpf)state,
sizeof
(
struct
inflate_state));
copy->strm = dest;
if
(state->lencode >= state->codes &&
state->lencode <= state->codes + ENOUGH - 1) {
copy->lencode = copy->codes + (state->lencode - state->codes);
copy->distcode = copy->codes + (state->distcode - state->codes);
}
copy->next = copy->codes + (state->next - state->codes);
if
(window != Z_NULL) {
wsize = 1U << state->wbits;
zmemcpy(window, state->window, wsize);
}
copy->window = window;
dest->state = (
struct
internal_state FAR *)copy;
return
Z_OK;
}
int
ZEXPORT inflateUndermine(z_streamp strm,
int
subvert) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
state->sane = !subvert;
return
Z_OK;
#else
(
void
)subvert;
state->sane = 1;
return
Z_DATA_ERROR;
#endif
}
int
ZEXPORT inflateValidate(z_streamp strm,
int
check) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
Z_STREAM_ERROR;
state = (
struct
inflate_state FAR *)strm->state;
if
(check && state->wrap)
state->wrap |= 4;
else
state->wrap &= ~4;
return
Z_OK;
}
long
ZEXPORT inflateMark(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
-(1L << 16);
state = (
struct
inflate_state FAR *)strm->state;
return
(
long
)(((unsigned
long
)((
long
)state->back)) << 16) +
(state->mode == COPY ? state->length :
(state->mode == MATCH ? state->was - state->length : 0));
}
unsigned
long
ZEXPORT inflateCodesUsed(z_streamp strm) {
struct
inflate_state FAR *state;
if
(inflateStateCheck(strm))
return
(unsigned
long
)-1;
state = (
struct
inflate_state FAR *)strm->state;
return
(unsigned
long
)(state->next - state->codes);
}