X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/1e1cf689348c43e24e1950a0bd25e691d85277ca..45574a73c156e389ab4aec98b6d30bb79d3ab367:/zlib/inflate.c diff --git a/zlib/inflate.c b/zlib/inflate.c index c6d38266..fd5ae4fe 100644 --- a/zlib/inflate.c +++ b/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2003 Mark Adler + * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -113,8 +113,11 @@ z_streamp strm; state->mode = HEAD; state->last = 0; state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; state->wsize = 0; state->whave = 0; + state->write = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -122,6 +125,22 @@ z_streamp strm; return Z_OK; } +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 > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) z_streamp strm; int windowBits; @@ -144,7 +163,7 @@ int stream_size; ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); - strm->state = (voidpf)state; + strm->state = (struct internal_state FAR *)state; if (windowBits < 0) { state->wrap = 0; windowBits = -windowBits; @@ -582,6 +601,8 @@ int flush; break; } state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( @@ -597,11 +618,13 @@ int flush; break; } DROPBITS(4); - if (BITS(4) + 8 > state->wbits) { + len = BITS(4) + 8; + if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } + state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; @@ -621,32 +644,55 @@ int flush; state->mode = BAD; break; } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; + /* FALL THROUGH */ case TIME: NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; + /* FALL THROUGH */ case OS: NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; + /* FALL THROUGH */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; state->mode = EXTRA; + /* FALL THROUGH */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; @@ -655,35 +701,52 @@ int flush; } if (state->length) goto inf_leave; } + state->length = 0; state->mode = NAME; + /* FALL THROUGH */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; } while (len && copy < have); - if (state->flags & 0x02000) + if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; state->mode = COMMENT; + /* FALL THROUGH */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; } while (len && copy < have); - if (state->flags & 0x02000) + if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; state->mode = HCRC; + /* FALL THROUGH */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); @@ -694,6 +757,10 @@ int flush; } INITBITS(); } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; @@ -703,6 +770,7 @@ int flush; strm->adler = state->check = REVERSE(hold); INITBITS(); state->mode = DICT; + /* FALL THROUGH */ case DICT: if (state->havedict == 0) { RESTORE(); @@ -710,8 +778,10 @@ int flush; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; + /* FALL THROUGH */ case TYPE: if (flush == Z_BLOCK) goto inf_leave; + /* FALL THROUGH */ case TYPEDO: if (state->last) { BYTEBITS(); @@ -757,6 +827,7 @@ int flush; state->length)); INITBITS(); state->mode = COPY; + /* FALL THROUGH */ case COPY: copy = state->length; if (copy) { @@ -792,6 +863,7 @@ int flush; Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; + /* FALL THROUGH */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); @@ -813,6 +885,7 @@ int flush; Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; + /* FALL THROUGH */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { @@ -887,6 +960,7 @@ int flush; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; + /* FALL THROUGH */ case LEN: if (have >= 6 && left >= 258) { RESTORE(); @@ -930,6 +1004,7 @@ int flush; } state->extra = (unsigned)(this.op) & 15; state->mode = LENEXT; + /* FALL THROUGH */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); @@ -938,6 +1013,7 @@ int flush; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->mode = DIST; + /* FALL THROUGH */ case DIST: for (;;) { this = state->distcode[BITS(state->distbits)]; @@ -963,12 +1039,20 @@ int flush; state->offset = (unsigned)this.val; state->extra = (unsigned)(this.op) & 15; state->mode = DISTEXT; + /* FALL THROUGH */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif if (state->offset > state->whave + out - left) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; @@ -976,6 +1060,7 @@ int flush; } Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; + /* FALL THROUGH */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; @@ -1031,6 +1116,7 @@ int flush; } #ifdef GUNZIP state->mode = LENGTH; + /* FALL THROUGH */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); @@ -1044,6 +1130,7 @@ int flush; } #endif state->mode = DONE; + /* FALL THROUGH */ case DONE: ret = Z_STREAM_END; goto inf_leave; @@ -1110,12 +1197,16 @@ uInt dictLength; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - if (state->mode != DICT) return Z_STREAM_ERROR; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; /* check for correct dictionary id */ - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) return Z_DATA_ERROR; + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } /* copy dictionary to window */ if (updatewindow(strm, strm->avail_out)) { @@ -1137,6 +1228,23 @@ uInt dictLength; return Z_OK; } +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes @@ -1239,6 +1347,7 @@ z_streamp source; struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; + unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || @@ -1261,14 +1370,19 @@ z_streamp source; } /* copy state */ - *dest = *source; - *copy = *state; - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) - zmemcpy(window, state->window, 1U << state->wbits); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } copy->window = window; - dest->state = (voidpf)copy; + dest->state = (struct internal_state FAR *)copy; return Z_OK; }