Commit 336bf96f authored by Jonas Termansen's avatar Jonas Termansen

Saturate instead of overflow in deflateBound and compressBound.

parent ae1691b2
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
deal safely with more than UINT_MAX bytes. deal safely with more than UINT_MAX bytes.
* Use asprintf where appropriate. * Use asprintf where appropriate.
* Better whether-this-value-fits-in-that-type checks. * Better whether-this-value-fits-in-that-type checks.
* Saturate instead of overflow in deflateBound and compressBound.
* Miscellaneous changes: * Miscellaneous changes:
* Remove uses of the register keyword. * Remove uses of the register keyword.
* Remove EQUAL macro. * Remove EQUAL macro.
......
...@@ -63,12 +63,22 @@ int ZEXPORT compress(unsigned char *dest, ...@@ -63,12 +63,22 @@ int ZEXPORT compress(unsigned char *dest,
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
} }
/* ========================================================================= */
static unsigned long saturateAddBound(unsigned long a, unsigned long b)
{
return ULONG_MAX - a < b ? ULONG_MAX : a + b;
}
/* =========================================================================== /* ===========================================================================
If the default memLevel or windowBits for deflateInit() is changed, then If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated. this function needs to be updated.
*/ */
unsigned long ZEXPORT compressBound(unsigned long sourceLen) unsigned long ZEXPORT compressBound(unsigned long sourceLen)
{ {
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + unsigned long complen = sourceLen;
(sourceLen >> 25) + 13; complen = saturateAddBound(complen, sourceLen >> 12);
complen = saturateAddBound(complen, sourceLen >> 14);
complen = saturateAddBound(complen, sourceLen >> 25);
complen = saturateAddBound(complen, 13);
return complen;
} }
...@@ -482,6 +482,12 @@ int ZEXPORT deflateTune(z_stream *strm, ...@@ -482,6 +482,12 @@ int ZEXPORT deflateTune(z_stream *strm,
return Z_OK; return Z_OK;
} }
/* ========================================================================= */
static unsigned long saturateAddBound(unsigned long a, unsigned long b)
{
return ULONG_MAX - a < b ? ULONG_MAX : a + b;
}
/* ========================================================================= /* =========================================================================
* For the default windowBits of 15 and memLevel of 8, this function returns * For the default windowBits of 15 and memLevel of 8, this function returns
* a close to exact, as well as small, upper bound on the compressed size. * a close to exact, as well as small, upper bound on the compressed size.
...@@ -507,12 +513,14 @@ unsigned long ZEXPORT deflateBound(z_stream *strm, ...@@ -507,12 +513,14 @@ unsigned long ZEXPORT deflateBound(z_stream *strm,
unsigned char *str; unsigned char *str;
/* conservative upper bound for compressed data */ /* conservative upper bound for compressed data */
complen = sourceLen + complen = sourceLen;
((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; complen = saturateAddBound(complen, (sourceLen + 7) >> 3);
complen = saturateAddBound(complen, (sourceLen + 63) >> 6);
complen = saturateAddBound(complen, 5);
/* if can't get parameters, return conservative bound plus zlib wrapper */ /* if can't get parameters, return conservative bound plus zlib wrapper */
if (strm == NULL || strm->state == NULL) if (strm == NULL || strm->state == NULL)
return complen + 6; return saturateAddBound(complen, 6);
/* compute wrapper length */ /* compute wrapper length */
s = strm->state; s = strm->state;
...@@ -526,33 +534,39 @@ unsigned long ZEXPORT deflateBound(z_stream *strm, ...@@ -526,33 +534,39 @@ unsigned long ZEXPORT deflateBound(z_stream *strm,
case 2: /* gzip wrapper */ case 2: /* gzip wrapper */
wraplen = 18; wraplen = 18;
if (s->gzhead != NULL) { /* user-supplied gzip header */ if (s->gzhead != NULL) { /* user-supplied gzip header */
if (s->gzhead->extra != NULL) if (s->gzhead->extra != NULL) {
wraplen += 2 + s->gzhead->extra_len; wraplen += 2;
wraplen = saturateAddBound(wraplen, s->gzhead->extra_len);
}
str = s->gzhead->name; str = s->gzhead->name;
if (str != NULL) if (str != NULL)
do { do {
wraplen++; wraplen = saturateAddBound(wraplen, 1);
} while (*str++); } while (*str++);
str = s->gzhead->comment; str = s->gzhead->comment;
if (str != NULL) if (str != NULL)
do { do {
wraplen++; wraplen = saturateAddBound(wraplen, 1);
} while (*str++); } while (*str++);
if (s->gzhead->hcrc) if (s->gzhead->hcrc)
wraplen += 2; wraplen = saturateAddBound(wraplen, 2);
} }
break; break;
default: /* for compiler happiness */ default:
wraplen = 6; wraplen = 6;
} }
/* if not default parameters, return conservative bound */ /* if not default parameters, return conservative bound */
if (s->w_bits != 15 || s->hash_bits != 8 + 7) if (s->w_bits != 15 || s->hash_bits != 8 + 7)
return complen + wraplen; return saturateAddBound(complen, wraplen);
/* default settings: return tight bound for that case */ /* default settings: return tight bound for that case */
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + complen = sourceLen;
(sourceLen >> 25) + 13 - 6 + wraplen; complen = saturateAddBound(complen, sourceLen >> 12);
complen = saturateAddBound(complen, sourceLen >> 14);
complen = saturateAddBound(complen, sourceLen >> 25);
complen = saturateAddBound(complen, 13 - 6);
return saturateAddBound(complen, wraplen);
} }
/* ========================================================================= /* =========================================================================
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment