state->mode = LEN;
case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= INFLATE_FAST_MIN_HAVE &&
+ left >= INFLATE_FAST_MIN_LEFT) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ zng_inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
/* get a literal, length, or end-of-block code */
for (;;) {
here = state->lencode[BITS(state->lenbits)];
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
-void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
+void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) {
+ /* start: inflate()'s starting value for strm->avail_out */
struct inflate_state *state;
z_const unsigned char *in; /* local strm->next_in */
const unsigned char *last; /* have enough input while in < last */
unsigned char *out; /* local strm->next_out */
+ unsigned char *beg; /* inflate()'s initial strm->next_out */
unsigned char *end; /* while out < end, enough space available */
+ unsigned char *safe; /* can use chunkcopy provided out < safe */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#endif
unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char *window; /* allocated sliding window, if wsize != 0 */
/* hold is a local copy of strm->hold. By default, hold satisfies the same
invariants that strm->hold does, namely that (hold >> bits) == 0. This
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
unsigned dist; /* match distance */
+ unsigned char *from; /* where to copy match from */
+ unsigned extra_safe; /* copy chunks safely in all cases */
/* copy state to local variables */
state = (struct inflate_state *)strm->state;
in = strm->next_in;
last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1));
- wsize = state->wsize;
- out = state->window + wsize + state->wnext;
- end = state->window + (wsize * 2) - (INFLATE_FAST_MIN_LEFT - 1);
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1));
+ safe = out + strm->avail_out;
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
hold = state->hold;
bits = state->bits;
lcode = state->lencode;
lmask = (1U << state->lenbits) - 1;
dmask = (1U << state->distbits) - 1;
+ /* Detect if out and window point to the same memory allocation. In this instance it is
+ necessary to use safe chunk copy functions to prevent overwriting the window. If the
+ window is overwritten then future matches with far distances will fail to copy correctly. */
+ extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize);
+
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
do {
in += 6;
bits += 48;
}
- if (out >= end) {
- state->wnext = (uint32_t)(out - (state->window + wsize));
- window_output_flush(strm);
- out = state->window + state->wsize + state->wnext;
- if (strm->avail_out == 0)
- break;
- }
here = lcode + (hold & lmask);
dolen:
DROPBITS(here->bits);
#endif
DROPBITS(op);
Tracevv((stderr, "inflate: distance %u\n", dist));
-
- if (out - dist < ((state->window + state->wsize) - state->whave)) {
- if (state->sane) {
- SET_BAD("invalid distance too far back");
- break;
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ SET_BAD("invalid distance too far back");
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
}
- }
-
- if (len > dist || dist < state->chunksize) {
- out = functable.chunkmemset(out, dist, len);
+ from = window;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ } else if (wnext >= op) { /* contiguous in window */
+ from += wnext - op;
+ } else { /* wrap around window */
+ op -= wnext;
+ from += wsize - op;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ out = chunkcopy_safe(out, from, op, safe);
+ from = window; /* more from start of window */
+ op = wnext;
+ /* This (rare) case can create a situation where
+ the first chunkcopy below must be checked.
+ */
+ }
+ }
+ if (op < len) { /* still need some from output */
+ len -= op;
+ out = chunkcopy_safe(out, from, op, safe);
+ out = functable.chunkunroll(out, &dist, &len);
+ out = chunkcopy_safe(out, out - dist, len, safe);
+ } else {
+ out = chunkcopy_safe(out, from, len, safe);
+ }
+ } else if (extra_safe) {
+ /* Whole reference is in range of current output. */
+ if (dist >= len || dist >= state->chunksize)
+ out = chunkcopy_safe(out, out - dist, len, safe);
+ else
+ out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1));
} else {
- out = functable.chunkcopy(out, out - dist, len);
+ /* Whole reference is in range of current output. No range checks are
+ necessary because we start with room for at least 258 bytes of output,
+ so unroll and roundoff operations can write beyond `out+len` so long
+ as they stay within 258 bytes of `out`.
+ */
+ if (dist >= len || dist >= state->chunksize)
+ out = functable.chunkcopy(out, out - dist, len);
+ else
+ out = functable.chunkmemset(out, dist, len);
}
} else if ((op & 64) == 0) { /* 2nd level distance code */
here = dcode + here->val + BITS(op);
SET_BAD("invalid literal/length code");
break;
}
- } while (in < last);
+ } while (in < last && out < end);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
/* update state and return */
strm->next_in = in;
+ strm->next_out = out;
strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in)
: (INFLATE_FAST_MIN_HAVE - 1) - (in - last));
+ strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out)
+ : (INFLATE_FAST_MIN_LEFT - 1) - (out - end));
- state->wnext = (uint32_t)(out - (state->window + state->wsize));
Assert(bits <= 32, "Remaining bits greater than 32");
state->hold = (uint32_t)hold;
state->bits = bits;
subject to change. Applications should only use zlib.h.
*/
-void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm);
+void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start);
#define INFLATE_FAST_MIN_HAVE 8
#define INFLATE_FAST_MIN_LEFT 258
/* function prototypes */
static int inflateStateCheck(PREFIX3(stream) *strm);
+static int updatewindow(PREFIX3(stream) *strm, const unsigned char *end, uint32_t copy);
static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len);
static int inflateStateCheck(PREFIX3(stream) *strm) {
if (inflateStateCheck(strm))
return Z_STREAM_ERROR;
state = (struct inflate_state *)strm->state;
+ state->wsize = 0;
state->whave = 0;
state->wnext = 0;
return PREFIX(inflateResetKeep)(strm);
if (state->window != NULL && state->wbits != (unsigned)windowBits) {
ZFREE_WINDOW(strm, state->window);
state->window = NULL;
- state->wsize = 0;
}
/* update state and reset the rest of it */
strm->state = (struct internal_state *)state;
state->strm = strm;
state->window = NULL;
- state->wsize = 0;
state->mode = HEAD; /* to pass state test in inflateReset2() */
state->chunksize = functable.chunksize();
ret = PREFIX(inflateReset2)(strm, windowBits);
if (ret != Z_OK) {
ZFREE_STATE(strm, state);
strm->state = NULL;
- return ret;
}
return ret;
}
/* if it hasn't been done already, allocate space for the window */
if (state->window == NULL) {
unsigned wsize = 1U << state->wbits;
- state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char));
+ state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char));
if (state->window == NULL)
return Z_MEM_ERROR;
memset(state->window + wsize, 0, state->chunksize);
return Z_OK;
}
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy) {
+ struct inflate_state *state;
+ uint32_t dist;
+
+ state = (struct inflate_state *)strm->state;
+
+ if (inflate_ensure_window(state)) return 1;
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state->wsize) {
+ memcpy(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;
+ memcpy(state->window + state->wnext, end - copy, dist);
+ copy -= dist;
+ if (copy) {
+ memcpy(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;
+}
+
/*
Private macros for inflate()
Look in inflate_p.h for macros shared with inflateBack()
unsigned bits; /* bits in bit buffer */
uint32_t in, out; /* save starting available input and output */
unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char *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 */
state->head->hcrc = (int)((state->flags >> 9) & 1);
state->head->done = 1;
}
- /* compute crc32 checksum if not in raw mode */
- if ((state->wrap & 4) && state->flags)
- strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold);
+ strm->adler = state->check = CRC32_INITIAL_VALUE;
state->mode = TYPE;
break;
#endif
goto inf_leave;
case TYPEDO:
- /* create window if it doesn't exist */
- if (state->window == NULL) {
- RESTORE();
- ret = inflate_ensure_window(state);
- if (ret != Z_OK) {
- ZFREE_STATE(strm, state);
- strm->state = NULL;
- return ret;
- }
- LOAD();
- }
/* determine and dispatch block type */
INFLATE_TYPEDO_HOOK(strm, flush); /* hook for IBM Z DFLTCC */
if (state->last) {
/* copy stored block from input to output */
copy = state->length;
if (copy) {
- unsigned char *end = state->window + (state->wsize * 2);
- int64_t diff = end - put;
-
copy = MIN(copy, have);
- if (copy > diff) {
- if (left > 0) {
- RESTORE();
- window_output_flush(strm);
- LOAD();
- diff = end - put;
- }
- copy = MIN(copy, (uint32_t)diff);
- }
+ copy = MIN(copy, left);
if (copy == 0)
goto inf_leave;
memcpy(put, next, copy);
have -= copy;
next += copy;
+ left -= copy;
put += copy;
state->length -= copy;
break;
/* use inflate_fast() if we have enough input and output */
if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) {
RESTORE();
- zng_inflate_fast(strm);
+ zng_inflate_fast(strm, out);
LOAD();
if (state->mode == TYPE)
state->back = -1;
Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH;
- case MATCH: {
+ case MATCH:
/* copy match from window to output */
if (left == 0)
goto inf_leave;
-
- unsigned char *end = state->window + (state->wsize * 2);
- int64_t buf_left = end - put;
- copy = state->length;
- RESTORE();
- if (copy > buf_left) {
- if (strm->avail_out > 0) {
- /* relies on RESTORE() above with no changes to those vars */
- window_output_flush(strm);
- LOAD();
- buf_left = end - put;
- }
- copy = MIN(copy, (uint32_t)buf_left);
- }
- if (copy == 0)
- goto inf_leave;
- if (state->offset > state->wnext + state->whave) {
- if (state->sane) {
- SET_BAD("invalid distance too far back");
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ SET_BAD("invalid distance too far back");
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ copy = MIN(copy, state->length);
+ copy = MIN(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);
+ }
+ copy = MIN(copy, state->length);
+ copy = MIN(copy, left);
+
+ put = chunkcopy_safe(put, from, copy, put + left);
+ } else {
+ copy = MIN(state->length, left);
+
+ put = functable.chunkmemset_safe(put, state->offset, copy, left);
}
- unsigned char *next_out = state->window + state->wsize + state->wnext;
- if (copy <= state->offset) {
- chunkcopy_safe(next_out, next_out - state->offset, copy, put + buf_left);
- } else { /* copy from output */
- functable.chunkmemset_safe(next_out, state->offset, copy, (uint32_t)buf_left);
- }
- state->wnext += copy;
+ left -= copy;
state->length -= copy;
- LOAD();
if (state->length == 0)
state->mode = LEN;
break;
- }
+
case LIT:
- if (put >= state->window + (state->wsize * 2)) {
- RESTORE();
- window_output_flush(strm);
- LOAD();
- }
if (left == 0)
goto inf_leave;
*put++ = (unsigned char)(state->length);
+ left--;
state->mode = LEN;
break;
case CHECK:
- RESTORE();
- window_output_flush(strm);
- LOAD();
- if (strm->avail_out == 0 && state->wnext)
- goto inf_leave;
if (state->wrap) {
NEEDBITS(32);
out -= left;
strm->total_out += out;
state->total += out;
-
- if (INFLATE_NEED_CHECKSUM(strm) && strm->total_out) {
- /* compute crc32 final value if not in raw mode */
- if ((state->wrap & 4) && state->flags)
- strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold);
- }
+ if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out)
+ strm->adler = state->check = UPDATE(state->check, put - out, out);
out = left;
if ((state->wrap & 4) && (
#ifdef GUNZIP
/*
Return from inflate(), updating the total counts and the check value.
If there was no progress during the inflate() call, return a buffer
- error.
+ error. Call updatewindow() to create and/or update the window state.
Note: a memory error from inflate() is non-recoverable.
*/
inf_leave:
RESTORE();
-
- if (strm->avail_out && state->wnext)
- window_output_flush(strm);
-
+ if (INFLATE_NEED_UPDATEWINDOW(strm) &&
+ (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 (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out)
+ strm->adler = state->check = UPDATE(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)
int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) {
struct inflate_state *state;
- unsigned long dictid, dict_copy, hist_copy;
- const unsigned char *dict_from, *hist_from;
- unsigned char *dict_to, *hist_to;
- int ret;
+ unsigned long dictid;
+ int32_t ret;
/* check state */
if (inflateStateCheck(strm))
if (dictid != state->check)
return Z_DATA_ERROR;
}
- ret = inflate_ensure_window(state);
- if (ret != Z_OK)
- return Z_MEM_ERROR;
- Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output"));
-
- /* copy dictionary to window and amend if necessary */
- dict_from = dictionary;
- dict_copy = dictLength;
- if (dict_copy > state->wsize) {
- dict_copy = state->wsize;
- dict_from += (dictLength - dict_copy);
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ ret = updatewindow(strm, dictionary + dictLength, dictLength);
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
}
- dict_to = state->window + state->wsize - dict_copy;
-
- hist_from = state->window + state->wsize - state->whave;
- hist_copy = state->wsize - dict_copy;
- if (hist_copy > state->whave)
- hist_copy = state->whave;
- hist_to = dict_to - hist_copy;
-
- if (hist_copy)
- memcpy(hist_to, hist_from, hist_copy);
- if (dict_copy)
- memcpy(dict_to, dict_from, dict_copy);
-
- state->whave = hist_copy + dict_copy;
state->havedict = 1;
Tracev((stderr, "inflate: dictionary set\n"));
return Z_OK;
window = NULL;
if (state->window != NULL) {
wsize = 1U << state->wbits;
- window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char));
+ window = (unsigned char *)ZALLOC_WINDOW(source, wsize, sizeof(unsigned char));
if (window == NULL) {
ZFREE_STATE(source, copy);
return Z_MEM_ERROR;
copy->next = copy->codes + (state->next - state->codes);
if (window != NULL) {
wsize = 1U << state->wbits;
- memcpy(window, state->window, (wsize * 2) + state->chunksize);
+ memcpy(window, state->window, wsize);
}
copy->window = window;
dest->state = (struct internal_state *)copy;
#ifndef INFLATE_H_
#define INFLATE_H_
-#include "crc32_fold.h"
-
/* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate().
NO_GZIP would be used to avoid linking in the crc code when it is not needed.
For shared libraries, gzip decoding should be left enabled. */
uint32_t wnext; /* window write index */
unsigned char *window; /* allocated sliding window, if needed */
- struct crc32_fold_s ALIGNED_(16) crc_fold;
-
/* bit accumulator */
uint32_t hold; /* input bit accumulator */
unsigned bits; /* number of bits in "in" */
#ifndef INFLATE_P_H
#define INFLATE_P_H
-#include "zbuild.h"
-#include "functable.h"
-
/* Architecture-specific hooks. */
#ifdef S390_DFLTCC_INFLATE
# include "arch/s390/dfltcc_inflate.h"
# define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
#endif
-
/*
* Macros shared by inflate() and inflateBack()
*/
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) functable.adler32(check, buf, len)
+#endif
+
/* check macros for header crc */
#ifdef GUNZIP
# define CRC2(check, word) \
/* Load registers with state in inflate() for speed */
#define LOAD() \
do { \
- put = state->window + state->wsize + state->wnext; \
+ put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
/* Restore state from registers in inflate() */
#define RESTORE() \
do { \
- state->wnext = (uint32_t)(put - (state->window + state->wsize)); \
+ strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = (z_const unsigned char *)next; \
strm->avail_in = have; \
strm->msg = (char *)errmsg; \
} while (0)
-
-static inline void inf_crc_copy(PREFIX3(stream) *strm, unsigned char *const dst,
- const unsigned char *const src, size_t len) {
- struct inflate_state *const state = (struct inflate_state *const)strm->state;
-
- if (!INFLATE_NEED_CHECKSUM(strm))
- return;
-
- /* compute checksum if not in raw mode */
- if (state->wrap & 4) {
- /* check flags to use adler32() for zlib or crc32() for gzip */
-#ifdef GUNZIP
- if (state->flags)
- functable.crc32_fold_copy(&state->crc_fold, dst, src, len);
- else
-#endif
- {
- memcpy(dst, src, len);
- strm->adler = state->check = functable.adler32(state->check, dst, len);
- }
- } else {
- memcpy(dst, src, len);
- }
-}
-
-static inline void window_output_flush(PREFIX3(stream) *strm) {
- struct inflate_state *const state = (struct inflate_state *const)strm->state;
- size_t write_offset, read_offset, copy_size;
- uint32_t out_bytes;
-
- if (state->wnext > strm->avail_out) {
- out_bytes = strm->avail_out;
- copy_size = state->wnext - out_bytes;
- } else {
- out_bytes = state->wnext;
- copy_size = 0;
- }
-
- /* Copy from pending buffer to stream output */
- inf_crc_copy(strm, strm->next_out, state->window + state->wsize, out_bytes);
-
- strm->avail_out -= out_bytes;
- strm->next_out += out_bytes;
-
- /* Discard bytes in sliding window */
- if (state->whave + out_bytes > state->wsize) {
- write_offset = 0;
- read_offset = out_bytes;
- copy_size += state->wsize;
- } else {
- read_offset = state->wsize - state->whave;
- write_offset = read_offset - out_bytes;
- copy_size += state->whave + out_bytes;
- }
-
- memmove(state->window + write_offset, state->window + read_offset, copy_size);
-
- state->wnext -= out_bytes;
- state->whave += out_bytes;
- state->whave = MIN(state->whave, state->wsize);
-}
-
/* Behave like chunkcopy, but avoid writing beyond of legal output. */
static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, unsigned len, uint8_t *safe) {
uint32_t safelen = (uint32_t)((safe - out) + 1);
mem_setup(&strm);
strm.avail_in = 0;
strm.next_in = NULL;
-
- mem_limit(&strm, 1);
- ret = PREFIX(inflateInit2)(&strm, win); assert(ret == Z_MEM_ERROR);
- mem_limit(&strm, 0);
ret = PREFIX(inflateInit2)(&strm, win);
if (ret != Z_OK) {
mem_done(&strm, what);
if (ret == Z_NEED_DICT) {
ret = PREFIX(inflateSetDictionary)(&strm, in, 1);
assert(ret == Z_DATA_ERROR);
+ mem_limit(&strm, 1);
+ ret = PREFIX(inflateSetDictionary)(&strm, out, 0);
+ assert(ret == Z_MEM_ERROR);
+ mem_limit(&strm, 0);
((struct inflate_state *)strm.state)->mode = DICT;
ret = PREFIX(inflateSetDictionary)(&strm, out, 0);
assert(ret == Z_OK);
strm.next_in = (void *)"\x63";
strm.avail_out = 1;
strm.next_out = (void *)&ret;
+ mem_limit(&strm, 1);
+ ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
+ ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR);
+ mem_limit(&strm, 0);
memset(dict, 0, 257);
ret = PREFIX(inflateSetDictionary)(&strm, dict, 257);
assert(ret == Z_OK);