| Index: third_party/zlib/inflate.c
|
| ===================================================================
|
| --- third_party/zlib/inflate.c (revision 113739)
|
| +++ third_party/zlib/inflate.c (working copy)
|
| @@ -1,5 +1,5 @@
|
| /* inflate.c -- zlib decompression
|
| - * Copyright (C) 1995-2005 Mark Adler
|
| + * Copyright (C) 1995-2010 Mark Adler
|
| * For conditions of distribution and use, see copyright notice in zlib.h
|
| */
|
|
|
| @@ -45,7 +45,7 @@
|
| * - Rearrange window copies in inflate_fast() for speed and simplification
|
| * - Unroll last copy for window match in inflate_fast()
|
| * - Use local copies of window variables in inflate_fast() for speed
|
| - * - Pull out common write == 0 case for speed in inflate_fast()
|
| + * - Pull out common wnext == 0 case for speed in inflate_fast()
|
| * - Make op and len in inflate_fast() unsigned for consistency
|
| * - Add FAR to lcode and dcode declarations in inflate_fast()
|
| * - Simplified bad distance check in inflate_fast()
|
| @@ -117,28 +117,52 @@
|
| state->head = Z_NULL;
|
| state->wsize = 0;
|
| state->whave = 0;
|
| - state->write = 0;
|
| + state->wnext = 0;
|
| 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 inflatePrime(strm, bits, value)
|
| +int ZEXPORT inflateReset2(strm, windowBits)
|
| z_streamp strm;
|
| -int bits;
|
| -int value;
|
| +int windowBits;
|
| {
|
| + int wrap;
|
| struct inflate_state FAR *state;
|
|
|
| + /* get the state */
|
| if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
| state = (struct inflate_state FAR *)strm->state;
|
| - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
|
| - value &= (1L << bits) - 1;
|
| - state->hold += value << state->bits;
|
| - state->bits += bits;
|
| - return Z_OK;
|
| +
|
| + /* extract wrap request from windowBits parameter */
|
| + if (windowBits < 0) {
|
| + wrap = 0;
|
| + windowBits = -windowBits;
|
| + }
|
| + else {
|
| + wrap = (windowBits >> 4) + 1;
|
| +#ifdef GUNZIP
|
| + if (windowBits < 48)
|
| + windowBits &= 15;
|
| +#endif
|
| + }
|
| +
|
| + /* set number of window bits, free window if different */
|
| + 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;
|
| + }
|
| +
|
| + /* update state and reset the rest of it */
|
| + state->wrap = wrap;
|
| + state->wbits = (unsigned)windowBits;
|
| + return inflateReset(strm);
|
| }
|
|
|
| int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
|
| @@ -147,6 +171,7 @@
|
| const char *version;
|
| int stream_size;
|
| {
|
| + int ret;
|
| struct inflate_state FAR *state;
|
|
|
| if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
| @@ -164,24 +189,13 @@
|
| if (state == Z_NULL) return Z_MEM_ERROR;
|
| Tracev((stderr, "inflate: allocated\n"));
|
| strm->state = (struct internal_state FAR *)state;
|
| - if (windowBits < 0) {
|
| - state->wrap = 0;
|
| - windowBits = -windowBits;
|
| - }
|
| - else {
|
| - state->wrap = (windowBits >> 4) + 1;
|
| -#ifdef GUNZIP
|
| - if (windowBits < 48) windowBits &= 15;
|
| -#endif
|
| - }
|
| - if (windowBits < 8 || windowBits > 15) {
|
| + state->window = Z_NULL;
|
| + ret = inflateReset2(strm, windowBits);
|
| + if (ret != Z_OK) {
|
| ZFREE(strm, state);
|
| strm->state = Z_NULL;
|
| - return Z_STREAM_ERROR;
|
| }
|
| - state->wbits = (unsigned)windowBits;
|
| - state->window = Z_NULL;
|
| - return inflateReset(strm);
|
| + return ret;
|
| }
|
|
|
| int ZEXPORT inflateInit_(strm, version, stream_size)
|
| @@ -192,6 +206,27 @@
|
| return inflateInit2_(strm, DEF_WBITS, version, stream_size);
|
| }
|
|
|
| +int ZEXPORT inflatePrime(strm, bits, value)
|
| +z_streamp strm;
|
| +int bits;
|
| +int value;
|
| +{
|
| + struct inflate_state FAR *state;
|
| +
|
| + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
| + state = (struct inflate_state FAR *)strm->state;
|
| + if (bits < 0) {
|
| + state->hold = 0;
|
| + state->bits = 0;
|
| + return Z_OK;
|
| + }
|
| + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
|
| + value &= (1L << bits) - 1;
|
| + state->hold += value << state->bits;
|
| + state->bits += bits;
|
| + return Z_OK;
|
| +}
|
| +
|
| /*
|
| Return state with length and distance decoding tables and index sizes set to
|
| fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
| @@ -340,7 +375,7 @@
|
| /* if window not in use yet, initialize */
|
| if (state->wsize == 0) {
|
| state->wsize = 1U << state->wbits;
|
| - state->write = 0;
|
| + state->wnext = 0;
|
| state->whave = 0;
|
| }
|
|
|
| @@ -348,22 +383,22 @@
|
| copy = out - strm->avail_out;
|
| if (copy >= state->wsize) {
|
| zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
|
| - state->write = 0;
|
| + state->wnext = 0;
|
| state->whave = state->wsize;
|
| }
|
| else {
|
| - dist = state->wsize - state->write;
|
| + dist = state->wsize - state->wnext;
|
| if (dist > copy) dist = copy;
|
| - zmemcpy(state->window + state->write, strm->next_out - copy, dist);
|
| + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
|
| copy -= dist;
|
| if (copy) {
|
| zmemcpy(state->window, strm->next_out - copy, copy);
|
| - state->write = copy;
|
| + state->wnext = copy;
|
| state->whave = state->wsize;
|
| }
|
| else {
|
| - state->write += dist;
|
| - if (state->write == state->wsize) state->write = 0;
|
| + state->wnext += dist;
|
| + if (state->wnext == state->wsize) state->wnext = 0;
|
| if (state->whave < state->wsize) state->whave += dist;
|
| }
|
| }
|
| @@ -564,7 +599,7 @@
|
| unsigned in, out; /* save starting available input and output */
|
| unsigned copy; /* number of stored or match bytes to copy */
|
| unsigned char FAR *from; /* where to copy match bytes from */
|
| - code this; /* current decoding table entry */
|
| + 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 */
|
| @@ -619,7 +654,9 @@
|
| }
|
| DROPBITS(4);
|
| len = BITS(4) + 8;
|
| - if (len > state->wbits) {
|
| + if (state->wbits == 0)
|
| + state->wbits = len;
|
| + else if (len > state->wbits) {
|
| strm->msg = (char *)"invalid window size";
|
| state->mode = BAD;
|
| break;
|
| @@ -771,7 +808,7 @@
|
| strm->adler = state->check = adler32(0L, Z_NULL, 0);
|
| state->mode = TYPE;
|
| case TYPE:
|
| - if (flush == Z_BLOCK) goto inf_leave;
|
| + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
|
| case TYPEDO:
|
| if (state->last) {
|
| BYTEBITS();
|
| @@ -791,7 +828,11 @@
|
| fixedtables(state);
|
| Tracev((stderr, "inflate: fixed codes block%s\n",
|
| state->last ? " (last)" : ""));
|
| - state->mode = LEN; /* decode codes */
|
| + state->mode = LEN_; /* decode codes */
|
| + if (flush == Z_TREES) {
|
| + DROPBITS(2);
|
| + goto inf_leave;
|
| + }
|
| break;
|
| case 2: /* dynamic block */
|
| Tracev((stderr, "inflate: dynamic codes block%s\n",
|
| @@ -816,6 +857,9 @@
|
| 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;
|
| @@ -876,19 +920,19 @@
|
| case CODELENS:
|
| 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) {
|
| + NEEDBITS(here.bits);
|
| + 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;
|
| @@ -898,16 +942,16 @@
|
| 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);
|
| @@ -925,7 +969,16 @@
|
| /* handle error breaks in while */
|
| if (state->mode == BAD) break;
|
|
|
| - /* build code tables */
|
| + /* 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;
|
| @@ -946,88 +999,102 @@
|
| 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 (;;) {
|
| - 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);
|
| + state->back += last.bits;
|
| }
|
| - DROPBITS(this.bits);
|
| - state->length = (unsigned)this.val;
|
| - if ((int)(this.op) == 0) {
|
| - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
| + 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", this.val));
|
| + "inflate: literal 0x%02x\n", here.val));
|
| state->mode = LIT;
|
| break;
|
| }
|
| - if (this.op & 32) {
|
| + if (here.op & 32) {
|
| Tracevv((stderr, "inflate: end of block\n"));
|
| + state->back = -1;
|
| state->mode = TYPE;
|
| break;
|
| }
|
| - if (this.op & 64) {
|
| + if (here.op & 64) {
|
| strm->msg = (char *)"invalid literal/length code";
|
| state->mode = BAD;
|
| break;
|
| }
|
| - state->extra = (unsigned)(this.op) & 15;
|
| + 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 (;;) {
|
| - 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);
|
| + state->back += last.bits;
|
| }
|
| - DROPBITS(this.bits);
|
| - if (this.op & 64) {
|
| + DROPBITS(here.bits);
|
| + state->back += here.bits;
|
| + if (here.op & 64) {
|
| strm->msg = (char *)"invalid distance code";
|
| state->mode = BAD;
|
| break;
|
| }
|
| - state->offset = (unsigned)this.val;
|
| - state->extra = (unsigned)(this.op) & 15;
|
| + 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) {
|
| @@ -1036,11 +1103,6 @@
|
| break;
|
| }
|
| #endif
|
| - if (state->offset > state->whave + out - left) {
|
| - strm->msg = (char *)"invalid distance too far back";
|
| - state->mode = BAD;
|
| - break;
|
| - }
|
| Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
| state->mode = MATCH;
|
| case MATCH:
|
| @@ -1048,12 +1110,32 @@
|
| copy = out - left;
|
| if (state->offset > copy) { /* copy from window */
|
| copy = state->offset - copy;
|
| - if (copy > state->write) {
|
| - copy -= state->write;
|
| + 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->write - copy);
|
| + from = state->window + (state->wnext - copy);
|
| if (copy > state->length) copy = state->length;
|
| }
|
| else { /* copy from output */
|
| @@ -1146,7 +1228,8 @@
|
| strm->adler = state->check =
|
| UPDATE(state->check, strm->next_out - out, out);
|
| strm->data_type = state->bits + (state->last ? 64 : 0) +
|
| - (state->mode == TYPE ? 128 : 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;
|
| @@ -1366,3 +1449,32 @@
|
| dest->state = (struct internal_state FAR *)copy;
|
| return Z_OK;
|
| }
|
| +
|
| +int ZEXPORT inflateUndermine(strm, subvert)
|
| +z_streamp strm;
|
| +int subvert;
|
| +{
|
| + struct inflate_state FAR *state;
|
| +
|
| + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
|
| + state = (struct inflate_state FAR *)strm->state;
|
| + state->sane = !subvert;
|
| +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
| + return Z_OK;
|
| +#else
|
| + state->sane = 1;
|
| + return Z_DATA_ERROR;
|
| +#endif
|
| +}
|
| +
|
| +long ZEXPORT inflateMark(strm)
|
| +z_streamp strm;
|
| +{
|
| + struct inflate_state FAR *state;
|
| +
|
| + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
|
| + state = (struct inflate_state FAR *)strm->state;
|
| + return ((long)(state->back) << 16) +
|
| + (state->mode == COPY ? state->length :
|
| + (state->mode == MATCH ? state->was - state->length : 0));
|
| +}
|
|
|