]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Revert "Reorganize inflate window layout"
authorNathan Moinvaziri <nathan@nathanm.com>
Mon, 7 Mar 2022 03:20:29 +0000 (19:20 -0800)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Wed, 23 Mar 2022 10:30:35 +0000 (11:30 +0100)
This reverts commit dc3b60841dbfa9cf37be3efb4568f055b4e15580.

infback.c
inffast.c
inffast.h
inflate.c
inflate.h
inflate_p.h
test/infcover.c

index 8c43a7cef89111a27303037545649a02bfc5fdec..c3f0fccc8a73affa8b555c40eced502840e0344d 100644 (file)
--- a/infback.c
+++ b/infback.c
@@ -338,6 +338,17 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in
             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)];
index 1dc1f789ece67bef9e3c97ef66dd849c1af3bae4..36923317de2d7e6dd6dcc43292f0eaf4f53c49e7 100644 (file)
--- a/inffast.c
+++ b/inffast.c
@@ -61,16 +61,22 @@ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) {
       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
@@ -120,17 +126,24 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
                                 /*  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;
@@ -138,6 +151,11 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
     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 {
@@ -146,13 +164,6 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
             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);
@@ -199,18 +210,76 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
 #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);
@@ -230,7 +299,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
             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;
@@ -240,10 +309,12 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) {
 
     /* 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;
index cf9a3e2d2bb1efe66975ddf9b59f72bc1abe5908..179a65da6019ad2c46af2b9a3353e0c41042c500 100644 (file)
--- a/inffast.h
+++ b/inffast.h
@@ -10,7 +10,7 @@
    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
index 419939b1474319dea856dc8be2cdba037dcf9fcb..11f7b5b084884d6debb10427aa6194cb6a9e5945 100644 (file)
--- a/inflate.c
+++ b/inflate.c
@@ -15,6 +15,7 @@
 
 /* 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) {
@@ -60,6 +61,7 @@ int32_t Z_EXPORT PREFIX(inflateReset)(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);
@@ -92,7 +94,6 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits
     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 */
@@ -125,14 +126,12 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits
     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;
 }
@@ -177,7 +176,7 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) {
     /* 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);
@@ -193,6 +192,54 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) {
     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()
@@ -298,6 +345,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
     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 */
@@ -499,9 +547,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
                 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
@@ -524,17 +570,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
                 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) {
@@ -591,24 +626,14 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
             /* 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;
@@ -744,7 +769,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
             /* 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;
@@ -859,74 +884,70 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
             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
@@ -976,21 +997,26 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) {
     /*
        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)
@@ -1031,10 +1057,8 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di
 
 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))
@@ -1049,33 +1073,14 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8
         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;
@@ -1215,7 +1220,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou
     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;
@@ -1233,7 +1238,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou
     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;
index 3f57e7840820486f126e47f9ddc170ae8240309f..67041348f765068b307b14664f4fd744b8dab45f 100644 (file)
--- a/inflate.h
+++ b/inflate.h
@@ -11,8 +11,6 @@
 #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. */
@@ -103,8 +101,6 @@ struct inflate_state {
     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" */
index fd3343a9bfb174765719e09fa4f05c64d4719289..2735c581dfd46ffba66eb6d8ab17cf3c36d68be5 100644 (file)
@@ -5,9 +5,6 @@
 #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) \
@@ -62,7 +66,7 @@
 /* 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; \
@@ -73,7 +77,7 @@
 /* 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);
index 0c355aa99c00caf4b5f361efcb121c684da335f6..974185d0a369ba68e8880fdfbdac27a66aa96c1f 100644 (file)
@@ -287,10 +287,6 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int
     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);
@@ -323,6 +319,10 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int
         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);
@@ -416,6 +416,10 @@ static void cover_wrap(void) {
     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);