120 lines
4.7 KiB
Diff
120 lines
4.7 KiB
Diff
From 0d36ec47f310478549c0864f215ab5c0114c49ba Mon Sep 17 00:00:00 2001
|
|
From: Mark Adler <madler@alumni.caltech.edu>
|
|
Date: Wed, 2 Jan 2019 18:10:40 -0800
|
|
Subject: [PATCH] Don't bother computing check value after successful
|
|
inflateSync().
|
|
|
|
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.
|
|
|
|
Reference:https://github.com/madler/zlib/commit/add7f08d50747956b6e336f258b7ad48
|
|
Conflict:NA
|
|
---
|
|
inflate.c | 14 ++++++++++----
|
|
inflate.h | 3 ++-
|
|
test/example.c | 5 ++---
|
|
3 files changed, 14 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/inflate.c b/inflate.c
|
|
index 575fcdf..2c1b17f 100644
|
|
--- a/inflate.c
|
|
+++ b/inflate.c
|
|
@@ -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;
|
|
@@ -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 */
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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;
|
|
}
|
|
diff --git a/inflate.h b/inflate.h
|
|
index a46cce6..98679fa 100644
|
|
--- a/inflate.h
|
|
+++ b/inflate.h
|
|
@@ -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 */
|
|
diff --git a/test/example.c b/test/example.c
|
|
index eee17ce..949f4f6 100644
|
|
--- a/test/example.c
|
|
+++ b/test/example.c
|
|
@@ -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);
|
|
--
|
|
2.23.0
|
|
|