You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
7.7 KiB
206 lines
7.7 KiB
Subject: [PATCH] Fixed DFLTCC compression level switching issues |
|
|
|
--- |
|
configure | 4 +-- |
|
contrib/s390/dfltcc.c | 52 ++++++++++++++++++++++++++++++----- |
|
contrib/s390/dfltcc_deflate.h | 2 ++ |
|
deflate.c | 12 ++++---- |
|
test/infcover.c | 2 +- |
|
5 files changed, 57 insertions(+), 15 deletions(-) |
|
|
|
diff --git a/configure b/configure |
|
index bfe4386..70ed86b 100755 |
|
--- a/configure |
|
+++ b/configure |
|
@@ -139,7 +139,7 @@ case "$1" in |
|
-w* | --warn) warn=1; shift ;; |
|
-d* | --debug) debug=1; shift ;; |
|
--dfltcc) |
|
- CFLAGS="$CFLAGS -DDFLTCC" |
|
+ CFLAGS="$CFLAGS -DDFLTCC -DDFLTCC_LEVEL_MASK=0x7e" |
|
OBJC="$OBJC dfltcc.o" |
|
PIC_OBJC="$PIC_OBJC dfltcc.lo" |
|
shift |
|
@@ -838,7 +838,7 @@ cat > $test.c << EOF |
|
#include <sys/sdt.h> |
|
int main() { return 0; } |
|
EOF |
|
-if try ${CC} ${CFLAGS} $test.c; then |
|
+ if try $CC -c $CFLAGS $test.c; then |
|
echo "Checking for sys/sdt.h ... Yes." | tee -a configure.log |
|
CFLAGS="$CFLAGS -DHAVE_SYS_SDT_H" |
|
SFLAGS="$SFLAGS -DHAVE_SYS_SDT_H" |
|
diff --git a/contrib/s390/dfltcc.c b/contrib/s390/dfltcc.c |
|
index d88a0d6..94a196f 100644 |
|
--- a/contrib/s390/dfltcc.c |
|
+++ b/contrib/s390/dfltcc.c |
|
@@ -350,8 +350,12 @@ int ZLIB_INTERNAL dfltcc_deflate(strm, flush, result) |
|
int soft_bcc; |
|
int no_flush; |
|
|
|
- if (!dfltcc_can_deflate(strm)) |
|
+ if (!dfltcc_can_deflate(strm)) { |
|
+ /* Clear history. */ |
|
+ if (flush == Z_FULL_FLUSH) |
|
+ param->hl = 0; |
|
return 0; |
|
+ } |
|
|
|
again: |
|
masked_avail_in = 0; |
|
@@ -376,7 +380,8 @@ again: |
|
/* Clear history. */ |
|
if (flush == Z_FULL_FLUSH) |
|
param->hl = 0; |
|
- *result = need_more; |
|
+ /* Trigger block post-processing if necessary. */ |
|
+ *result = no_flush ? need_more : block_done; |
|
return 1; |
|
} |
|
|
|
@@ -403,13 +408,18 @@ again: |
|
param->bcf = 0; |
|
dfltcc_state->block_threshold = |
|
strm->total_in + dfltcc_state->block_size; |
|
- if (strm->avail_out == 0) { |
|
- *result = need_more; |
|
- return 1; |
|
- } |
|
} |
|
} |
|
|
|
+ /* No space for compressed data. If we proceed, dfltcc_cmpr() will return |
|
+ * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still |
|
+ * set BCF=1, which is wrong. Avoid complications and return early. |
|
+ */ |
|
+ if (strm->avail_out == 0) { |
|
+ *result = need_more; |
|
+ return 1; |
|
+ } |
|
+ |
|
/* The caller gave us too much data. Pass only one block worth of |
|
* uncompressed data to DFLTCC and mask the rest, so that on the next |
|
* iteration we start a new block. |
|
@@ -737,10 +747,15 @@ __attribute__((constructor)) local void init_globals(void) |
|
* compiling with -m31, gcc defaults to ESA mode, however, since the kernel |
|
* is 64-bit, it's always z/Architecture mode at runtime. |
|
*/ |
|
- __asm__ volatile(".machinemode push\n" |
|
+ __asm__ volatile( |
|
+#ifndef __clang__ |
|
+ ".machinemode push\n" |
|
".machinemode zarch\n" |
|
+#endif |
|
"stfle %[facilities]\n" |
|
+#ifndef __clang__ |
|
".machinemode pop\n" |
|
+#endif |
|
: [facilities] "=Q" (cpu_facilities) |
|
, [r0] "+r" (r0) |
|
: |
|
@@ -872,6 +887,28 @@ int ZLIB_INTERNAL dfltcc_deflate_params(strm, level, strategy, flush) |
|
return Z_OK; |
|
} |
|
|
|
+int ZLIB_INTERNAL dfltcc_deflate_done(strm, flush) |
|
+ z_streamp strm; |
|
+ int flush; |
|
+{ |
|
+ deflate_state FAR *state = (deflate_state FAR *)strm->state; |
|
+ struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state); |
|
+ struct dfltcc_param_v0 FAR *param = &dfltcc_state->param; |
|
+ |
|
+ /* When deflate(Z_FULL_FLUSH) is called with small avail_out, it might |
|
+ * close the block without resetting the compression state. Detect this |
|
+ * situation and return that deflation is not done. |
|
+ */ |
|
+ if (flush == Z_FULL_FLUSH && strm->avail_out == 0) |
|
+ return 0; |
|
+ |
|
+ /* Return that deflation is not done if DFLTCC is used and either it |
|
+ * buffered some data (Continuation Flag is set), or has not written EOBS |
|
+ * yet (Block-Continuation Flag is set). |
|
+ */ |
|
+ return !dfltcc_can_deflate(strm) || (!param->cf && !param->bcf); |
|
+} |
|
+ |
|
/* |
|
Preloading history. |
|
*/ |
|
@@ -925,6 +962,7 @@ int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(strm, dictionary, dict_length) |
|
|
|
append_history(param, state->window, dictionary, dict_length); |
|
state->strstart = 1; /* Add FDICT to zlib header */ |
|
+ state->block_start = state->strstart; /* Make deflate_stored happy */ |
|
return Z_OK; |
|
} |
|
|
|
diff --git a/contrib/s390/dfltcc_deflate.h b/contrib/s390/dfltcc_deflate.h |
|
index de36784..914daa4 100644 |
|
--- a/contrib/s390/dfltcc_deflate.h |
|
+++ b/contrib/s390/dfltcc_deflate.h |
|
@@ -11,6 +11,7 @@ int ZLIB_INTERNAL dfltcc_deflate_params OF((z_streamp strm, |
|
int level, |
|
int strategy, |
|
int *flush)); |
|
+int ZLIB_INTERNAL dfltcc_deflate_done OF((z_streamp strm, int flush)); |
|
int ZLIB_INTERNAL dfltcc_deflate_set_dictionary OF((z_streamp strm, |
|
const Bytef *dictionary, |
|
uInt dict_length)); |
|
@@ -41,6 +42,7 @@ int ZLIB_INTERNAL dfltcc_deflate_get_dictionary OF((z_streamp strm, |
|
if (err == Z_STREAM_ERROR) \ |
|
return err; \ |
|
} while (0) |
|
+#define DEFLATE_DONE dfltcc_deflate_done |
|
#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \ |
|
do { \ |
|
if (dfltcc_can_deflate((strm))) \ |
|
diff --git a/deflate.c b/deflate.c |
|
index d907a1b..085abbe 100644 |
|
--- a/deflate.c |
|
+++ b/deflate.c |
|
@@ -75,6 +75,7 @@ const char deflate_copyright[] = |
|
#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) |
|
#define DEFLATE_RESET_KEEP_HOOK(strm) do {} while (0) |
|
#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0) |
|
+#define DEFLATE_DONE(strm, flush) 1 |
|
#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0) |
|
#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) 0 |
|
#define DEFLATE_HOOK(strm, flush, bstate) 0 |
|
@@ -605,14 +606,15 @@ int ZEXPORT deflateParams(strm, level, strategy) |
|
DEFLATE_PARAMS_HOOK(strm, level, strategy, &hook_flush); |
|
func = configuration_table[s->level].func; |
|
|
|
- if ((strategy != s->strategy || func != configuration_table[level].func || |
|
- hook_flush != Z_NO_FLUSH) && s->last_flush != -2) { |
|
+ if (((strategy != s->strategy || func != configuration_table[level].func) && |
|
+ s->last_flush != -2) || hook_flush != Z_NO_FLUSH) { |
|
/* Flush the last buffer: */ |
|
- int err = deflate(strm, RANK(hook_flush) > RANK(Z_BLOCK) ? |
|
- hook_flush : Z_BLOCK); |
|
+ int flush = RANK(hook_flush) > RANK(Z_BLOCK) ? hook_flush : Z_BLOCK; |
|
+ int err = deflate(strm, flush); |
|
if (err == Z_STREAM_ERROR) |
|
return err; |
|
- if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) |
|
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead || |
|
+ !DEFLATE_DONE(strm, flush)) |
|
return Z_BUF_ERROR; |
|
} |
|
if (s->level != level) { |
|
diff --git a/test/infcover.c b/test/infcover.c |
|
index a34cd17..a208219 100644 |
|
--- a/test/infcover.c |
|
+++ b/test/infcover.c |
|
@@ -373,7 +373,7 @@ local void cover_support(void) |
|
mem_setup(&strm); |
|
strm.avail_in = 0; |
|
strm.next_in = Z_NULL; |
|
- ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); |
|
+ ret = inflateInit_(&strm, &ZLIB_VERSION[1], (int)sizeof(z_stream)); |
|
assert(ret == Z_VERSION_ERROR); |
|
mem_done(&strm, "wrong version"); |
|
|
|
-- |
|
2.26.0 |
|
|
|
|