]> 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>
Mon, 20 Dec 2021 13:49:27 +0000 (14:49 +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 de45e29e6a2aaea214cd9f8b8c6d926d167341a9..fded2a4cdf65b37cd1d76e050c94a1c239da8f0e 100644 (file)
@@ -91,10 +91,11 @@ z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) {
         return complen + ZLIB_WRAPLEN;
 
 #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 bb20a7d7a683f4cfcf326a65c38330b00d33c165..8f569bf2e57bba2bbb9c271df1eefd0b3ebb51f3 100644 (file)
--- a/deflate.c
+++ b/deflate.c
@@ -611,11 +611,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) {
@@ -639,7 +639,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 */
@@ -647,8 +647,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 e7cb9ad3e470744f9607c4fdf19236bd723865a1..f25556f946cd9a4cbbea0d214cc16891cf499f14 100644 (file)
--- a/zutil.h
+++ b/zutil.h
@@ -78,7 +78,19 @@ 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 CRC32_INITIAL_VALUE   0 /* initial crc-32 hash value */
 
-#define ZLIB_WRAPLEN 6 /* zlib format overhead */
+#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 */