From: Mark Adler Date: Tue, 25 Oct 2016 03:11:41 +0000 (-0700) Subject: Do a more thorough check of the state for every stream call. X-Git-Tag: 1.9.9-b1~732 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6d55bd6a784d881a4b778c9354f462bde1ceee12;p=thirdparty%2Fzlib-ng.git Do a more thorough check of the state for every stream call. This verifies that the state has been initialized, that it is the expected type of state, deflate or inflate, and that at least the first several bytes of the internal state have not been clobbered. --- diff --git a/deflate.c b/deflate.c index 33c660335..4c0e55a48 100644 --- a/deflate.c +++ b/deflate.c @@ -68,6 +68,7 @@ const char deflate_copyright[] = " deflate 1.2.8.f Copyright 1995-2013 Jean-loup typedef block_state (*compress_func) (deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ +static int deflateStateCheck (z_stream *strm); static block_state deflate_stored (deflate_state *s, int flush); block_state deflate_fast (deflate_state *s, int flush); block_state deflate_quick (deflate_state *s, int flush); @@ -218,6 +219,7 @@ int ZEXPORT deflateInit2_(z_stream *strm, int level, int method, int windowBits, return Z_MEM_ERROR; strm->state = (struct internal_state *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = NULL; @@ -269,6 +271,26 @@ int ZEXPORT deflateInit2_(z_stream *strm, int level, int method, int windowBits, return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +static int deflateStateCheck (z_stream *strm) { + deflate_state *s; + if (strm == NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == NULL || s->strm != strm || (s->status != INIT_STATE && + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ int ZEXPORT deflateSetDictionary(z_stream *strm, const unsigned char *dictionary, unsigned int dictLength) { deflate_state *s; @@ -277,7 +299,7 @@ int ZEXPORT deflateSetDictionary(z_stream *strm, const unsigned char *dictionary uint32_t avail; const unsigned char *next; - if (strm == NULL || strm->state == NULL || dictionary == NULL) + if (deflateStateCheck(strm) || dictionary == NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; @@ -331,7 +353,7 @@ int ZEXPORT deflateSetDictionary(z_stream *strm, const unsigned char *dictionary int ZEXPORT deflateResetKeep(z_stream *strm) { deflate_state *s; - if (strm == NULL || strm->state == NULL || strm->zalloc == NULL || strm->zfree == NULL) { + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -371,9 +393,7 @@ int ZEXPORT deflateReset(z_stream *strm) { /* ========================================================================= */ int ZEXPORT deflateSetHeader(z_stream *strm, gz_headerp head) { - if (strm == NULL || strm->state == NULL) - return Z_STREAM_ERROR; - if (strm->state->wrap != 2) + if (deflateStateCheck(strm) || strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; @@ -381,7 +401,7 @@ int ZEXPORT deflateSetHeader(z_stream *strm, gz_headerp head) { /* ========================================================================= */ int ZEXPORT deflatePending(z_stream *strm, uint32_t *pending, int *bits) { - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != NULL) *pending = strm->state->pending; @@ -395,7 +415,7 @@ int ZEXPORT deflatePrime(z_stream *strm, int bits, int value) { deflate_state *s; int put; - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; if ((unsigned char *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) @@ -419,7 +439,7 @@ int ZEXPORT deflateParams(z_stream *strm, int level, int strategy) { compress_func func; int err = Z_OK; - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; @@ -451,7 +471,7 @@ int ZEXPORT deflateParams(z_stream *strm, int level, int strategy) { int ZEXPORT deflateTune(z_stream *strm, int good_length, int max_lazy, int nice_length, int max_chain) { deflate_state *s; - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; s->good_match = (unsigned int)good_length; @@ -487,7 +507,7 @@ unsigned long ZEXPORT deflateBound(z_stream *strm, unsigned long sourceLen) { complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return complen + 6; /* compute wrapper length */ @@ -576,7 +596,7 @@ int ZEXPORT deflate(z_stream *strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == NULL || strm->state == NULL || flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; @@ -882,19 +902,10 @@ int ZEXPORT deflate(z_stream *strm, int flush) { int ZEXPORT deflateEnd(z_stream *strm) { int status; - if (strm == NULL || strm->state == NULL) + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -916,7 +927,7 @@ int ZEXPORT deflateCopy(z_stream *dest, z_stream *source) { deflate_state *ss; uint16_t *overlay; - if (source == NULL || dest == NULL || source->state == NULL) { + if (deflateStateCheck(source) || dest == NULL) { return Z_STREAM_ERROR; } diff --git a/inflate.c b/inflate.c index f0a341501..298479f86 100644 --- a/inflate.c +++ b/inflate.c @@ -92,6 +92,7 @@ #endif /* function prototypes */ +static int inflateStateCheck(z_stream *strm); static void fixedtables(struct inflate_state *state); static int updatewindow(z_stream *strm, const unsigned char *end, uint32_t copy); #ifdef BUILDFIXED @@ -99,10 +100,20 @@ static int updatewindow(z_stream *strm, const unsigned char *end, uint32_t copy) #endif static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); +static int inflateStateCheck(z_stream *strm) { + struct inflate_state *state; + if (strm == NULL || strm->zalloc == NULL || strm->zfree == NULL) + return 1; + state = (struct inflate_state *)strm->state; + if (state == NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + int ZEXPORT inflateResetKeep(z_stream *strm) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; strm->total_in = strm->total_out = state->total = 0; @@ -126,7 +137,7 @@ int ZEXPORT inflateResetKeep(z_stream *strm) { int ZEXPORT inflateReset(z_stream *strm) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; state->wsize = 0; @@ -140,7 +151,7 @@ int ZEXPORT inflateReset2(z_stream *strm, int windowBits) { struct inflate_state *state; /* get the state */ - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; @@ -190,7 +201,9 @@ int ZEXPORT inflateInit2_(z_stream *strm, int windowBits, const char *version, i return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state *)state; + state->strm = strm; state->window = NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -206,7 +219,7 @@ int ZEXPORT inflateInit_(z_stream *strm, const char *version, int stream_size) { int ZEXPORT inflatePrime(z_stream *strm, int bits, int value) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (bits < 0) { @@ -592,7 +605,7 @@ int ZEXPORT inflate(z_stream *strm, int flush) { static const uint16_t order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == NULL || strm->state == NULL || strm->next_out == NULL || + if (inflateStateCheck(strm) || strm->next_out == NULL || (strm->next_in == NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -1228,7 +1241,7 @@ int ZEXPORT inflate(z_stream *strm, int flush) { int ZEXPORT inflateEnd(z_stream *strm) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL || strm->zfree == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (state->window != NULL) @@ -1243,7 +1256,7 @@ int ZEXPORT inflateGetDictionary(z_stream *strm, unsigned char *dictionary, unsi struct inflate_state *state; /* check state */ - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; @@ -1263,7 +1276,7 @@ int ZEXPORT inflateSetDictionary(z_stream *strm, const unsigned char *dictionary int ret; /* check state */ - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (state->wrap != 0 && state->mode != DICT) @@ -1293,7 +1306,7 @@ int ZEXPORT inflateGetHeader(z_stream *strm, gz_headerp head) { struct inflate_state *state; /* check state */ - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if ((state->wrap & 2) == 0) @@ -1342,7 +1355,7 @@ int ZEXPORT inflateSync(z_stream *strm) { struct inflate_state *state; /* check parameters */ - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (strm->avail_in == 0 && state->bits < 8) @@ -1392,7 +1405,7 @@ int ZEXPORT inflateSync(z_stream *strm) { int ZEXPORT inflateSyncPoint(z_stream *strm) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; return state->mode == STORED && state->bits == 0; @@ -1405,8 +1418,7 @@ int ZEXPORT inflateCopy(z_stream *dest, z_stream *source) { unsigned wsize; /* check input */ - if (dest == NULL || source == NULL || source->state == NULL || - source->zalloc == NULL || source->zfree == NULL) + if (inflateStateCheck(source) || dest == NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)source->state; @@ -1427,6 +1439,7 @@ int ZEXPORT inflateCopy(z_stream *dest, z_stream *source) { /* copy state */ memcpy((void *)dest, (void *)source, sizeof(z_stream)); memcpy((void *)copy, (void *)state, sizeof(struct inflate_state)); + copy->strm = dest; 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); @@ -1444,7 +1457,7 @@ int ZEXPORT inflateCopy(z_stream *dest, z_stream *source) { int ZEXPORT inflateUndermine(z_stream *strm, int subvert) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR @@ -1460,7 +1473,8 @@ int ZEXPORT inflateUndermine(z_stream *strm, int subvert) { int ZEXPORT inflateValidate(z_stream *strm, int check) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (check) state->wrap |= 4; @@ -1472,7 +1486,7 @@ int ZEXPORT inflateValidate(z_stream *strm, int check) { long ZEXPORT inflateMark(z_stream *strm) { struct inflate_state *state; - if (strm == NULL || strm->state == NULL) + if (inflateStateCheck(strm)) return -65536; state = (struct inflate_state *)strm->state; return ((long)(state->back) << 16) + (state->mode == COPY ? state->length : diff --git a/inflate.h b/inflate.h index e33330a82..a1849e089 100644 --- a/inflate.h +++ b/inflate.h @@ -21,7 +21,7 @@ /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -83,6 +83,7 @@ typedef enum { /* State maintained between inflate() calls -- approximately 7K bytes, not including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_stream *strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,