From 8a378ba9b85e23a6e2e67b01a1b3d738e86faefe Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 13 Dec 2021 22:30:58 +0100 Subject: Fix deflateBound and compressBound returning very small size estimates. Remove workaround in switchlevels.c, so we do actual testing of this. Use named defines instead of magic numbers where we can. --- compress.c | 11 ++++++----- deflate.c | 16 +++++++++++----- test/switchlevels.c | 2 +- zutil.h | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/compress.c b/compress.c index d537959..46e8f8e 100644 --- a/compress.c +++ b/compress.c @@ -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 } diff --git a/deflate.c b/deflate.c index ca9dafa..031a1bb 100644 --- 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 } /* ========================================================================= diff --git a/test/switchlevels.c b/test/switchlevels.c index a4ec4b7..1e1fb00 100644 --- a/test/switchlevels.c +++ b/test/switchlevels.c @@ -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 c9e769c..015219a 100644 --- 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 -- cgit v1.2.3