Add option to not compute or check check values.

The undocumented (except in these commit comments) function
inflateValidate(strm, check) can be called after an inflateInit(),
inflateInit2(), or inflateReset2() with check equal to zero to
turn off the check value (CRC-32 or Adler-32) computation and
comparison. Calling with check not equal to zero turns checking
back on. This should only be called immediately after the init or
reset function. inflateReset() does not change the state, so a
previous inflateValidate() setting will remain in effect.

This also turns off validation of the gzip header CRC when
present.

This should only be used when a zlib or gzip stream has already
been checked, and repeated decompressions of the same stream no
longer need to be validated.
This commit is contained in:
Mark Adler 2016-09-20 18:49:21 -07:00
parent 93b0af4aa7
commit 9852c209ac
3 changed files with 34 additions and 13 deletions

View File

@ -156,7 +156,7 @@ int windowBits;
windowBits = -windowBits;
}
else {
wrap = (windowBits >> 4) + 1;
wrap = (windowBits >> 4) + 5;
#ifdef GUNZIP
if (windowBits < 48)
windowBits &= 15;
@ -701,14 +701,16 @@ int flush;
}
if (state->head != Z_NULL)
state->head->text = (int)((hold >> 8) & 1);
if (state->flags & 0x0200) CRC2(state->check, hold);
if ((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
case TIME:
NEEDBITS(32);
if (state->head != Z_NULL)
state->head->time = hold;
if (state->flags & 0x0200) CRC4(state->check, hold);
if ((state->flags & 0x0200) && (state->wrap & 4))
CRC4(state->check, hold);
INITBITS();
state->mode = OS;
case OS:
@ -717,7 +719,8 @@ int flush;
state->head->xflags = (int)(hold & 0xff);
state->head->os = (int)(hold >> 8);
}
if (state->flags & 0x0200) CRC2(state->check, hold);
if ((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
case EXLEN:
@ -726,7 +729,8 @@ int flush;
state->length = (unsigned)(hold);
if (state->head != Z_NULL)
state->head->extra_len = (unsigned)hold;
if (state->flags & 0x0200) CRC2(state->check, hold);
if ((state->flags & 0x0200) && (state->wrap & 4))
CRC2(state->check, hold);
INITBITS();
}
else if (state->head != Z_NULL)
@ -744,7 +748,7 @@ int flush;
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);
}
if (state->flags & 0x0200)
if ((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
@ -765,7 +769,7 @@ int flush;
state->length < state->head->name_max)
state->head->name[state->length++] = len;
} while (len && copy < have);
if (state->flags & 0x0200)
if ((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
@ -786,7 +790,7 @@ int flush;
state->length < state->head->comm_max)
state->head->comment[state->length++] = len;
} while (len && copy < have);
if (state->flags & 0x0200)
if ((state->flags & 0x0200) && (state->wrap & 4))
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
@ -798,7 +802,7 @@ int flush;
case HCRC:
if (state->flags & 0x0200) {
NEEDBITS(16);
if (hold != (state->check & 0xffff)) {
if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
strm->msg = (char *)"header crc mismatch";
state->mode = BAD;
break;
@ -1179,11 +1183,11 @@ int flush;
out -= left;
strm->total_out += out;
state->total += out;
if (out)
if ((state->wrap & 4) && out)
strm->adler = state->check =
UPDATE(state->check, put - out, out);
out = left;
if ((
if ((state->wrap & 4) && (
#ifdef GUNZIP
state->flags ? hold :
#endif
@ -1242,7 +1246,7 @@ int flush;
strm->total_in += in;
strm->total_out += out;
state->total += out;
if (state->wrap && out)
if ((state->wrap & 4) && out)
strm->adler = state->check =
UPDATE(state->check, strm->next_out - out, out);
strm->data_type = state->bits + (state->last ? 64 : 0) +
@ -1501,6 +1505,21 @@ int subvert;
#endif
}
int ZEXPORT inflateValidate(strm, check)
z_streamp strm;
int check;
{
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 (check)
state->wrap |= 4;
else
state->wrap &= ~4;
return Z_OK;
}
long ZEXPORT inflateMark(strm)
z_streamp strm;
{

View File

@ -82,7 +82,8 @@ typedef enum {
struct inflate_state {
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 */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */

1
zlib.h
View File

@ -1769,6 +1769,7 @@ ZEXTERN const char * ZEXPORT zError OF((int));
ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)