]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Fix deflateBound and compressBound returning very small size estimates.
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Mon, 13 Dec 2021 21:30:58 +0000 (22:30 +0100)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 24 Dec 2021 11:52:14 +0000 (12:52 +0100)
Remove workaround in switchlevels.c, so we do actual testing of this.
Use named defines instead of magic numbers where we can.

compress.c
deflate.c
test/switchlevels.c
zutil.h

index d5379591d1ca9f13c24f6e9f67830a2ef59f19cf..46e8f8e37d165c748deff0531fafefb137b00f53 100644 (file)
@@ -3,8 +3,8 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-#define ZLIB_INTERNAL
 #include "zbuild.h"
+#include "zutil.h"
 #if defined(ZLIB_COMPAT)
 #  include "zlib.h"
 #else
@@ -74,10 +74,11 @@ int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsi
  */
 z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) {
 #ifndef NO_QUICK_STRATEGY
-    /* Quick deflate strategy worse case is 9 bits per literal, rounded to nearest byte,
-       plus the size of block & gzip headers and footers */
-    return sourceLen + ((sourceLen + 13 + 7) >> 3) + 18;
+    return sourceLen                       /* The source size itself */
+      + DEFLATE_QUICK_OVERHEAD(sourceLen)  /* Source encoding overhead, padded to next full byte */
+      + DEFLATE_BLOCK_OVERHEAD             /* Deflate block overhead bytes */
+      + ZLIB_WRAPLEN;                      /* zlib wrapper */
 #else
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
+    return sourceLen + (sourceLen >> 4) + 7 + ZLIB_WRAPLEN;
 #endif
 }
index ca9dafa8db48b1cd0501cd64bda8fe68fad18d56..031a1bb086297a6ae7ff4ab116126c9b98a4b886 100644 (file)
--- a/deflate.c
+++ b/deflate.c
@@ -685,11 +685,11 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
         wraplen = 0;
         break;
     case 1:                                 /* zlib wrapper */
-        wraplen = 6 + (s->strstart ? 4 : 0);
+        wraplen = ZLIB_WRAPLEN + (s->strstart ? 4 : 0);
         break;
 #ifdef GZIP
     case 2:                                 /* gzip wrapper */
-        wraplen = 18;
+        wraplen = GZIP_WRAPLEN;
         if (s->gzhead != NULL) {            /* user-supplied gzip header */
             unsigned char *str;
             if (s->gzhead->extra != NULL) {
@@ -713,7 +713,7 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
         break;
 #endif
     default:                                /* for compiler happiness */
-        wraplen = 6;
+        wraplen = ZLIB_WRAPLEN;
     }
 
     /* if not default parameters, return conservative bound */
@@ -721,8 +721,14 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
             s->w_bits != 15 || HASH_BITS < 15)
         return complen + wraplen;
 
-    /* default settings: return tight bound for that case */
-    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen;
+#ifndef NO_QUICK_STRATEGY
+    return sourceLen                       /* The source size itself */
+      + DEFLATE_QUICK_OVERHEAD(sourceLen)  /* Source encoding overhead, padded to next full byte */
+      + DEFLATE_BLOCK_OVERHEAD             /* Deflate block overhead bytes */
+      + wraplen;                           /* none, zlib or gzip wrapper */
+#else
+    return sourceLen + (sourceLen >> 4) + 7 + wraplen;
+#endif
 }
 
 /* =========================================================================
index a4ec4b7c76c8d2f3bc1970797edf954f8959acdd..1e1fb00a5cffa950f1a80a572f5c6ae2fbcbee13 100644 (file)
@@ -68,7 +68,7 @@ static int compress_chunk(PREFIX3(stream) *strm, int level, int size, int last)
         goto done;
     }
 
-    compsize = 100 + 2 * PREFIX(deflateBound)(strm, size);
+    compsize = PREFIX(deflateBound)(strm, size);
     buf = malloc(size + compsize);
     if (buf == NULL) {
         fprintf(stderr, "Out of memory\n");
diff --git a/zutil.h b/zutil.h
index c9e769c6b67be368d2d4166f6c84876e35b07528..015219ae2e6ee0601adecff7c1909e2f4c353e8c 100644 (file)
--- a/zutil.h
+++ b/zutil.h
@@ -78,6 +78,20 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */
 
 #define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */
 
+#define ZLIB_WRAPLEN 6      /* zlib format overhead */
+#define GZIP_WRAPLEN 18     /* gzip format overhead */
+
+#define DEFLATE_HEADER_BITS 3
+#define DEFLATE_EOBS_BITS   15
+#define DEFLATE_PAD_BITS    6
+#define DEFLATE_BLOCK_OVERHEAD ((DEFLATE_HEADER_BITS + DEFLATE_EOBS_BITS + DEFLATE_PAD_BITS) >> 3)
+/* deflate block overhead: 3 bits for block start + 15 bits for block end + padding to nearest byte */
+
+#define DEFLATE_QUICK_LIT_MAX_BITS 9
+#define DEFLATE_QUICK_OVERHEAD(x) ((x * (DEFLATE_QUICK_LIT_MAX_BITS - 8) + 7) >> 3)
+/* deflate_quick worst-case overhead: 9 bits per literal, round up to next byte (+7) */
+
+
         /* target dependencies */
 
 #ifdef AMIGA