Index: third_party/zlib/inflate.c |
=================================================================== |
--- third_party/zlib/inflate.c (revision 112951) |
+++ 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)); |
+} |