]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
IBM Z: Adjust compressBound() for DFLTCC
authorIlya Leoshkevich <iii@linux.ibm.com>
Mon, 11 Oct 2021 10:24:20 +0000 (12:24 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 24 Dec 2021 11:52:14 +0000 (12:52 +0100)
When DFLTCC was introduced, deflateBound() was adjusted, but
compressBound() was not, leading to compression failures when using
compressBound() + compress() with poorly compressible data.

arch/s390/dfltcc_common.h
arch/s390/dfltcc_deflate.h
compress.c
zutil.h

index f46f9cafb266e0fc8858282f84bf89f651fd5d91..6de8bb18f6518122ed23dcb68cb3cdd6c3ea4e47 100644 (file)
@@ -26,4 +26,28 @@ void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w);
 
 #define TRY_FREE_WINDOW dfltcc_free_window
 
+#define DFLTCC_BLOCK_HEADER_BITS 3
+#define DFLTCC_HLITS_COUNT_BITS 5
+#define DFLTCC_HDISTS_COUNT_BITS 5
+#define DFLTCC_HCLENS_COUNT_BITS 4
+#define DFLTCC_MAX_HCLENS 19
+#define DFLTCC_HCLEN_BITS 3
+#define DFLTCC_MAX_HLITS 286
+#define DFLTCC_MAX_HDISTS 30
+#define DFLTCC_MAX_HLIT_HDIST_BITS 7
+#define DFLTCC_MAX_SYMBOL_BITS 16
+#define DFLTCC_MAX_EOBS_BITS 15
+#define DFLTCC_MAX_PADDING_BITS 7
+
+#define DEFLATE_BOUND_COMPLEN(source_len) \
+    ((DFLTCC_BLOCK_HEADER_BITS + \
+      DFLTCC_HLITS_COUNT_BITS + \
+      DFLTCC_HDISTS_COUNT_BITS + \
+      DFLTCC_HCLENS_COUNT_BITS + \
+      DFLTCC_MAX_HCLENS * DFLTCC_HCLEN_BITS + \
+      (DFLTCC_MAX_HLITS + DFLTCC_MAX_HDISTS) * DFLTCC_MAX_HLIT_HDIST_BITS + \
+      (source_len) * DFLTCC_MAX_SYMBOL_BITS + \
+      DFLTCC_MAX_EOBS_BITS + \
+      DFLTCC_MAX_PADDING_BITS) >> 3)
+
 #endif
index 7e32380bd8923e19d3aa882162a0d2386b82a1df..218e5946932de08b60f8b8943ed713eca493fe83 100644 (file)
@@ -41,8 +41,7 @@ int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha
 #define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \
     do { \
         if (dfltcc_can_deflate((strm))) \
-            (complen) = (3 + 5 + 5 + 4 + 19 * 3 + (286 + 30) * 7 + \
-                         (source_len) * 16 + 15 + 7) >> 3; \
+            (complen) = DEFLATE_BOUND_COMPLEN(source_len); \
     } while (0)
 
 #define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm)))
index 46e8f8e37d165c748deff0531fafefb137b00f53..fded2a4cdf65b37cd1d76e050c94a1c239da8f0e 100644 (file)
 #  include "zlib-ng.h"
 #endif
 
+/* ===========================================================================
+ *  Architecture-specific hooks.
+ */
+#ifdef S390_DFLTCC_DEFLATE
+#  include "arch/s390/dfltcc_common.h"
+#else
+/* Returns the upper bound on compressed data length based on uncompressed data length, assuming default settings.
+ * Zero means that arch-specific deflation code behaves identically to the regular zlib-ng algorithms. */
+#  define DEFLATE_BOUND_COMPLEN(source_len) 0
+#endif
+
 /* ===========================================================================
      Compresses the source buffer into the destination buffer. The level
    parameter has the same meaning as in deflateInit.  sourceLen is the byte
@@ -73,6 +84,12 @@ int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsi
    this function needs to be updated.
  */
 z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) {
+    z_size_t complen = DEFLATE_BOUND_COMPLEN(sourceLen);
+
+    if (complen > 0)
+        /* Architecture-specific code provided an upper bound. */
+        return complen + ZLIB_WRAPLEN;
+
 #ifndef NO_QUICK_STRATEGY
     return sourceLen                       /* The source size itself */
       + DEFLATE_QUICK_OVERHEAD(sourceLen)  /* Source encoding overhead, padded to next full byte */
diff --git a/zutil.h b/zutil.h
index 015219ae2e6ee0601adecff7c1909e2f4c353e8c..7578737170f22bc2319d69869f88e584a90d34d7 100644 (file)
--- a/zutil.h
+++ b/zutil.h
@@ -92,6 +92,8 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */
 /* deflate_quick worst-case overhead: 9 bits per literal, round up to next byte (+7) */
 
 
+#define ZLIB_WRAPLEN 6 /* zlib format overhead */
+
         /* target dependencies */
 
 #ifdef AMIGA