# define GZBUFSIZE 131072
#endif
+/* upper limit on the requested buffer size; the allocation is three times this,
+ so the cap keeps that total well inside an unsigned and far above any size
+ that is useful in practice */
+#ifndef GZBUFSIZE_MAX
+# define GZBUFSIZE_MAX (1u << 30) /* 1 GiB */
+#endif
+
/* gzip modes, also provide a little integrity check on the passed structure */
#define GZ_NONE 0
#define GZ_READ 7247
out_size = want * 2; // double output buffer for decompression
}
- /* the total reaches 3 * want but gzbuffer only guards 2 * want; cap against
- INT_MAX (minus zng_alloc_aligned's overhead) and reject rather than wrap */
- const size_t aligned_overhead = sizeof(void *) + 64;
- const size_t max_size = (size_t)INT_MAX - aligned_overhead;
- if (out_size > max_size || in_size > max_size - out_size) {
- PREFIX(gz_error)(state, Z_MEM_ERROR, "out of memory");
- return -1;
- }
-
+ /* gzbuffer caps want at GZBUFSIZE_MAX, so the total here stays inside the
+ unsigned that zng_alloc_aligned takes */
state->buffers = (unsigned char *)zng_alloc_aligned((unsigned)(in_size + out_size), 64);
state->in = state->buffers;
if (out_size) {
return -1;
/* check and set requested size */
- if ((size << 1) < size)
- return -1; /* need to be able to double it */
+ if (size > GZBUFSIZE_MAX) {
+#ifdef ZLIB_COMPAT
+ size = GZBUFSIZE_MAX; /* silently clamp to stay compatible with zlib */
+#else
+ return -1; /* too large */
+#endif
+ }
if (size < 8)
size = 8; /* needed to behave well with flushing */
state->want = size;
If zlib-ng is compiled with 'WITH_REDUCED_MEM' set, the default buffer size
is reduced to 8192 bytes.
+ The requested size is limited to 1 GiB, which is far larger than is useful
+ in practice. zng_gzbuffer() returns -1 when a larger size is requested,
+ while the zlib-compatible gzbuffer() silently clamps it to 1 GiB.
+
The new buffer size also affects the maximum length for gzprintf().
gzbuffer() returns 0 on success, or -1 on failure, such as being called