Skip to content

Commit

Permalink
Don't bother computing check value after successful inflateSync().
Browse files Browse the repository at this point in the history
inflateSync() is used to skip invalid deflate data, which means
that the check value that was being computed is no longer useful.
This commit turns off the check value computation, and furthermore
allows a successful return if the compressed data terminated in a
graceful manner. This commit also fixes a bug in the case that
inflateSync() is used before a header is ever processed. In that
case, there is no knowledge of a trailer, so the remainder is
treated as raw.
  • Loading branch information
madler committed Jan 3, 2019
1 parent 7c0c75e commit 0d36ec4
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 8 deletions.
14 changes: 10 additions & 4 deletions inflate.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ z_streamp strm;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
state->flags = -1;
state->dmax = 32768U;
state->head = Z_NULL;
state->hold = 0;
Expand Down Expand Up @@ -670,7 +671,6 @@ int flush;
state->mode = FLAGS;
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 */
Expand All @@ -697,6 +697,7 @@ int flush;
break;
}
state->dmax = 1U << len;
state->flags = 0; /* indicate zlib header */
Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
Expand Down Expand Up @@ -1221,7 +1222,7 @@ int flush;
case LENGTH:
if (state->wrap && state->flags) {
NEEDBITS(32);
if (hold != (state->total & 0xffffffffUL)) {
if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
strm->msg = (char *)"incorrect length check";
state->mode = BAD;
break;
Expand Down Expand Up @@ -1401,6 +1402,7 @@ int ZEXPORT inflateSync(strm)
z_streamp strm;
{
unsigned len; /* number of bytes to look at or looked at */
int flags; /* temporary to save header status */
unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state;
Expand Down Expand Up @@ -1433,11 +1435,15 @@ z_streamp strm;

/* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR;
if (state->mode == HEAD)
state->wrap = 0; /* never processed header, so assume raw */
if (state->flags == -1)
state->wrap = 0; /* if no header yet, treat as raw */
else
state->wrap &= ~4; /* no point in computing a check value now */
flags = state->flags;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
state->flags = flags;
state->mode = TYPE;
return Z_OK;
}
Expand Down
3 changes: 2 additions & 1 deletion inflate.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ struct inflate_state {
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) */
int flags; /* gzip header method and flags, 0 if zlib, or
-1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
Expand Down
5 changes: 2 additions & 3 deletions test/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,9 +440,8 @@ void test_sync(compr, comprLen, uncompr, uncomprLen)
CHECK_ERR(err, "inflateSync");

err = inflate(&d_stream, Z_FINISH);
if (err != Z_DATA_ERROR) {
fprintf(stderr, "inflate should report DATA_ERROR\n");
/* Because of incorrect adler32 */
if (err != Z_STREAM_END) {
fprintf(stderr, "inflate should report Z_STREAM_END\n");
exit(1);
}
err = inflateEnd(&d_stream);
Expand Down

0 comments on commit 0d36ec4

Please sign in to comment.