From 5c7d5a215916465539707ec6886380d9046e7266 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 12:24:20 +0200 Subject: IBM Z: Adjust compressBound() for DFLTCC 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 | 24 ++++++++++++++++++++++++ arch/s390/dfltcc_deflate.h | 3 +-- compress.c | 17 +++++++++++++++++ zutil.h | 2 ++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index f46f9ca..6de8bb1 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -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 diff --git a/arch/s390/dfltcc_deflate.h b/arch/s390/dfltcc_deflate.h index 7e32380..218e594 100644 --- a/arch/s390/dfltcc_deflate.h +++ b/arch/s390/dfltcc_deflate.h @@ -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))) diff --git a/compress.c b/compress.c index 46e8f8e..fded2a4 100644 --- a/compress.c +++ b/compress.c @@ -11,6 +11,17 @@ # 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 015219a..7578737 100644 --- 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 -- cgit v1.2.3