/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
-z_stream FAR *strm;
+z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
- if (strm->zalloc == 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 == Z_NULL) strm->zfree = zcfree;
+ 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 = (voidpf)state;
- state->wbits = windowBits;
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = (uInt)windowBits;
state->wsize = 1U << windowBits;
state->window = window;
- state->write = 0;
+ state->wnext = 0;
+ state->whave = 0;
return Z_OK;
}
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
- goto leave; \
+ goto inf_leave; \
} \
} \
} while (0)
if (left == 0) { \
put = state->window; \
left = state->wsize; \
+ state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
- goto leave; \
+ goto inf_leave; \
} \
} \
} while (0)
in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
- window, it called out() to write out the data. The application must not
+ window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
-z_stream FAR *strm;
+z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state;
- unsigned char *next, *put; /* next input and output */
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
- unsigned char *from; /* where to copy match bytes from */
- code this; /* current decoding table entry */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
+ state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
- this = state->lencode[BITS(state->lenbits)];
- if ((unsigned)(this.bits) <= bits) break;
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
- if (this.val < 16) {
- NEEDBITS(this.bits);
- DROPBITS(this.bits);
- state->lens[state->have++] = this.val;
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
}
else {
- if (this.val == 16) {
- NEEDBITS(this.bits + 2);
- DROPBITS(this.bits);
+ 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;
copy = 3 + BITS(2);
DROPBITS(2);
}
- else if (this.val == 17) {
- NEEDBITS(this.bits + 3);
- DROPBITS(this.bits);
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
- NEEDBITS(this.bits + 7);
- DROPBITS(this.bits);
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
}
- /* build code tables */
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
+ /* fallthrough */
case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
/* get a literal, length, or end-of-block code */
for (;;) {
- this = state->lencode[BITS(state->lenbits)];
- if ((unsigned)(this.bits) <= bits) break;
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
- if (this.op && (this.op & 0xf0) == 0) {
- last = this;
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
for (;;) {
- this = state->lencode[last.val +
+ here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
- if ((unsigned)(last.bits + this.bits) <= bits) break;
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
- DROPBITS(this.bits);
- state->length = (unsigned)this.val;
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
/* process literal */
- if (this.op == 0) {
- Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", this.val));
+ "inflate: literal 0x%02x\n", here.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
}
/* process end of block */
- if (this.op & 32) {
+ if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}
/* invalid code */
- if (this.op & 64) {
+ if (here.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}
/* length code -- get extra bits, if any */
- state->extra = (unsigned)(this.op) & 15;
+ state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
/* get distance code */
for (;;) {
- this = state->distcode[BITS(state->distbits)];
- if ((unsigned)(this.bits) <= bits) break;
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
PULLBYTE();
}
- if ((this.op & 0xf0) == 0) {
- last = this;
+ if ((here.op & 0xf0) == 0) {
+ last = here;
for (;;) {
- this = state->distcode[last.val +
+ here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
- if ((unsigned)(last.bits + this.bits) <= bits) break;
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
- DROPBITS(this.bits);
- if (this.op & 64) {
+ DROPBITS(here.bits);
+ if (here.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
- state->offset = (unsigned)this.val;
+ state->offset = (unsigned)here.val;
/* get distance extra bits, if any */
- state->extra = (unsigned)(this.op) & 15;
+ state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
- if (state->offset > state->wsize) {
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
- goto leave;
+ goto inf_leave;
case BAD:
ret = Z_DATA_ERROR;
- goto leave;
+ goto inf_leave;
default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
- goto leave;
+ goto inf_leave;
}
/* Return unused input */
- leave:
+ inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}
int ZEXPORT inflateBackEnd(strm)
-z_stream FAR *strm;
+z_streamp strm;
{
- if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == Z_NULL)
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;