0
0
mirror of https://github.com/madler/zlib.git synced 2026-01-18 17:11:27 +01:00

Add compressBound_z and deflateBound_z functions for large values.

These take and return size_t integers, instead of unsigned longs,
for those platforms with 32-bit longs. This commit also assures
that overflows of either integer type results in the maximum value
for that type, instead of wrapping to small values.
This commit is contained in:
Mark Adler
2026-01-04 10:34:44 -06:00
parent fd366384cf
commit 916dc1ac35
15 changed files with 90 additions and 16 deletions

View File

@@ -69,7 +69,12 @@ int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
uLong ZEXPORT compressBound(uLong sourceLen) {
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13;
z_size_t ZEXPORT compressBound_z(z_size_t sourceLen) {
z_size_t bound = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13;
return bound < sourceLen ? (z_size_t)-1 : bound;
}
uLong ZEXPORT compressBound(uLong sourceLen) {
z_size_t bound = compressBound_z(sourceLen);
return (uLong)bound != bound ? (uLong)-1 : (uLong)bound;
}

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -159,3 +159,7 @@ EXPORTS
; zlib1 v1.3.1.2 added:
deflateUsed @179
; zlib1 v1.3.2 added:
compressBound_z @180
deflateBound_z @181

View File

@@ -839,24 +839,30 @@ int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
*
* Shifts are used to approximate divisions, for speed.
*/
uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen) {
deflate_state *s;
uLong fixedlen, storelen, wraplen;
z_size_t fixedlen, storelen, wraplen, bound;
/* upper bound for fixed blocks with 9-bit literals and length 255
(memLevel == 2, which is the lowest that may not use stored blocks) --
~13% overhead plus a small constant */
fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
(sourceLen >> 9) + 4;
if (fixedlen < sourceLen)
fixedlen = (z_size_t)-1;
/* upper bound for stored blocks with length 127 (memLevel == 1) --
~4% overhead plus a small constant */
storelen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) +
(sourceLen >> 11) + 7;
if (storelen < sourceLen)
storelen = (z_size_t)-1;
/* if can't get parameters, return larger bound plus a wrapper */
if (deflateStateCheck(strm))
return (fixedlen > storelen ? fixedlen : storelen) + 18;
if (deflateStateCheck(strm)) {
bound = fixedlen > storelen ? fixedlen : storelen;
return bound + 18 < bound ? (z_size_t)-1 : bound + 18;
}
/* compute wrapper length */
s = strm->state;
@@ -894,14 +900,21 @@ uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
}
/* if not default parameters, return one of the conservative bounds */
if (s->w_bits != 15 || s->hash_bits != 8 + 7)
return (s->w_bits <= s->hash_bits && s->level ? fixedlen : storelen) +
wraplen;
if (s->w_bits != 15 || s->hash_bits != 8 + 7) {
bound = s->w_bits <= s->hash_bits && s->level ? fixedlen :
storelen;
return bound + wraplen < bound ? (z_size_t)-1 : bound + wraplen;
}
/* default settings: return tight bound for that case -- ~0.03% overhead
plus a small constant */
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13 - 6 + wraplen;
bound = sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13 - 6 + wraplen;
return bound < sourceLen ? (z_size_t)-1 : bound;
}
uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) {
z_size_t bound = deflateBound_z(strm, sourceLen);
return (uLong)bound != bound ? (uLong)-1 : (uLong)bound;
}
/* =========================================================================

View File

@@ -125,9 +125,16 @@ STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
EXPORT SYMBOL("crc32_combine_op")
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
/* Version 1.3.1.2 additional entry points. */
/* Version 1.3.1.2 additional entry points. */
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
EXPORT SYMBOL("deflateUsed")
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
/* Version 1.3.2 additional entry points. */
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
EXPORT SYMBOL("compressBound_z")
EXPORT SYMBOL("deflateBound_z")
ENDPGMEXP

View File

@@ -127,6 +127,9 @@
D compressBound PR 10U 0 extproc('compressBound')
D sourceLen 10U 0 value
*
D compressBound_z PR 20U 0 extproc('compressBound')
D sourceLen 20U 0 value
*
D uncompress PR 10I 0 extproc('uncompress')
D dest 65535 options(*varsize) Destination buffer
D destLen 10U 0 Destination length
@@ -366,6 +369,10 @@
D strm like(z_stream) Compression stream
D sourcelen 10U 0 value Compression level
*
D deflateBound_z PR 20U 0 extproc('deflateBound') Change level & strat
D strm like(z_stream) Compression stream
D sourcelen 20U 0 value Compression level
*
D deflatePending PR 10I 0 extproc('deflatePending') Change level & strat
D strm like(z_stream) Compression stream
D pending 10U 0 Pending bytes

View File

@@ -14,6 +14,7 @@ EXPORTS
deflateParams
deflateTune
deflateBound
deflateBound_z
deflatePending
deflateUsed
deflatePrime
@@ -34,6 +35,7 @@ EXPORTS
compress
compress2
compressBound
compressBound_z
uncompress
uncompress2
gzopen

View File

@@ -34,6 +34,7 @@
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define compressBound_z z_compressBound_z
# endif
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
@@ -44,6 +45,7 @@
# define crc32_z z_crc32_z
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateBound_z z_deflateBound_z
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateGetDictionary z_deflateGetDictionary

View File

@@ -34,6 +34,7 @@
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define compressBound_z z_compressBound_z
# endif
# define crc32 z_crc32
# define crc32_combine z_crc32_combine
@@ -44,6 +45,7 @@
# define crc32_z z_crc32_z
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateBound_z z_deflateBound_z
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateGetDictionary z_deflateGetDictionary

11
zlib.h
View File

@@ -765,8 +765,8 @@ ZEXTERN int ZEXPORT deflateTune(z_streamp strm,
returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
*/
ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
uLong sourceLen);
ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen);
ZEXTERN z_size_t ZEXPORT deflateBound_z(z_streamp strm, z_size_t sourceLen);
/*
deflateBound() returns an upper bound on the compressed size after
deflation of sourceLen bytes. It must be called after deflateInit() or
@@ -778,6 +778,9 @@ ZEXTERN uLong ZEXPORT deflateBound(z_streamp strm,
to return Z_STREAM_END. Note that it is possible for the compressed size to
be larger than the value returned by deflateBound() if flush options other
than Z_FINISH or Z_NO_FLUSH are used.
delfateBound_z() is the same, but takes and returns a size_t length for
those systems on which a long is 32 bits.
*/
ZEXTERN int ZEXPORT deflatePending(z_streamp strm,
@@ -1293,10 +1296,14 @@ ZEXTERN int ZEXPORT compress2(Bytef *dest, uLongf *destLen,
*/
ZEXTERN uLong ZEXPORT compressBound(uLong sourceLen);
ZEXTERN z_size_t ZEXPORT compressBound_z(z_size_t sourceLen);
/*
compressBound() returns an upper bound on the compressed size after
compress() or compress2() on sourceLen bytes. It would be used before a
compress() or compress2() call to allocate the destination buffer.
compressBound_z() is the same, but takes and returns a size_t length for
those systems on which a long is 32 bits.
*/
ZEXTERN int ZEXPORT uncompress(Bytef *dest, uLongf *destLen,

View File

@@ -101,4 +101,9 @@ ZLIB_1.2.12 {
ZLIB_1.3.1.2 {
deflateUsed;
} ZLIB_1.2.12;
} ZLIB_1.2.12;
ZLIB_1.3.2 {
compressBound_z;
deflateBound_z;
} ZLIB_1.3.1.2;