# include "internal/dso.h"
/* Function pointers */
-typedef int (*compress_ft) (Bytef *dest, uLongf * destLen,
+typedef int (*compress_ft) (Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen);
+typedef int (*uncompress_ft) (Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen);
typedef int (*inflateEnd_ft) (z_streamp strm);
typedef int (*inflate_ft) (z_streamp strm, int flush);
typedef int (*inflateInit__ft) (z_streamp strm,
const char *version, int stream_size);
typedef const char *(*zError__ft) (int err);
static compress_ft p_compress = NULL;
+static uncompress_ft p_uncompress = NULL;
static inflateEnd_ft p_inflateEnd = NULL;
static inflate_ft p_inflate = NULL;
static inflateInit__ft p_inflateInit_ = NULL;
static DSO *zlib_dso = NULL;
# define compress p_compress
+# define uncompress p_uncompress
# define inflateEnd p_inflateEnd
# define inflate p_inflate
# define inflateInit_ p_inflateInit_
return (ossl_ssize_t)(olen - state->istream.avail_out);
}
+/* ONESHOT COMPRESSION/DECOMPRESSION */
+
+static int zlib_oneshot_init(COMP_CTX *ctx)
+{
+ return 1;
+}
+
+static void zlib_oneshot_finish(COMP_CTX *ctx)
+{
+}
+
+static ossl_ssize_t zlib_oneshot_compress_block(COMP_CTX *ctx, unsigned char *out,
+ size_t olen, unsigned char *in,
+ size_t ilen)
+{
+ uLongf out_size;
+
+ if (ilen == 0)
+ return 0;
+
+ /* zlib's uLongf defined as unsigned long FAR */
+ if (olen > ULONG_MAX)
+ return -1;
+ out_size = (uLongf)olen;
+
+ if (compress(out, &out_size, in, ilen) != Z_OK)
+ return -1;
+
+ if (out_size > OSSL_SSIZE_MAX)
+ return -1;
+ return (ossl_ssize_t)out_size;
+}
+
+static ossl_ssize_t zlib_oneshot_expand_block(COMP_CTX *ctx, unsigned char *out,
+ size_t olen, unsigned char *in,
+ size_t ilen)
+{
+ uLongf out_size;
+
+ if (ilen == 0)
+ return 0;
+
+ /* zlib's uLongf defined as unsigned long FAR */
+ if (olen > ULONG_MAX)
+ return -1;
+ out_size = (uLongf)olen;
+
+ if (uncompress(out, &out_size, in, ilen) != Z_OK)
+ return -1;
+
+ if (out_size > OSSL_SSIZE_MAX)
+ return -1;
+ return (ossl_ssize_t)out_size;
+}
+
+static COMP_METHOD zlib_oneshot_method = {
+ NID_zlib_compression,
+ LN_zlib_compression,
+ zlib_oneshot_init,
+ zlib_oneshot_finish,
+ zlib_oneshot_compress_block,
+ zlib_oneshot_expand_block
+};
+
static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)
{
zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
if (zlib_dso != NULL) {
p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress");
+ p_uncompress = (compress_ft) DSO_bind_func(zlib_dso, "uncompress");
p_inflateEnd = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd");
p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate");
p_inflateInit_ = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_");
p_deflateInit_ = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_");
p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError");
- if (p_compress == NULL || p_inflateEnd == NULL
+ if (p_compress == NULL || p_uncompress == NULL || p_inflateEnd == NULL
|| p_inflate == NULL || p_inflateInit_ == NULL
|| p_deflateEnd == NULL || p_deflate == NULL
|| p_deflateInit_ == NULL || p_zError == NULL) {
return meth;
}
+COMP_METHOD *COMP_zlib_oneshot(void)
+{
+ COMP_METHOD *meth = NULL;
+
+#ifndef OPENSSL_NO_ZLIB
+ if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
+ meth = &zlib_oneshot_method;
+#endif
+
+ return meth;
+}
+
/* Also called from OPENSSL_cleanup() */
void ossl_comp_zlib_cleanup(void)
{
COMP_compress_block,
COMP_expand_block,
COMP_zlib,
+COMP_zlib_oneshot,
COMP_brotli,
COMP_brotli_oneshot,
COMP_zstd,
unsigned char *in, int ilen);
COMP_METHOD *COMP_zlib(void);
+ COMP_METHOD *COMP_zlib_oneshot(void);
COMP_METHOD *COMP_brotli(void);
COMP_METHOD *COMP_brotli_oneshot(void);
COMP_METHOD *COMP_zstd(void);
=item *
+COMP_zlib_oneshot() returns a B<COMP_METHOD> for one-shot ZLIB compression.
+
+=item *
+
COMP_brotli() returns a B<COMP_METHOD> for stream-based Brotli compression.
=item *
Internal state (including compression dictionary) is maintained between calls.
If an error is returned, the stream is corrupted, and should be closed.
-COMP_brotli_oneshot() and COMP_zstd_oneshot() are not stream-based. These
+COMP_zlib_oneshot(), COMP_brotli_oneshot() and COMP_zstd_oneshot() are not stream-based. These
methods do not maintain state between calls. An error in one call does not affect
future calls.
COMP_CTX_new() returns a B<COMP_CTX> on success, or NULL on failure.
-COMP_CTX_get_method(), COMP_zlib(), COMP_brotli(), COMP_brotli_oneshot(),
+COMP_CTX_get_method(), COMP_zlib(), COMP_zlib_oneshot(), COMP_brotli(), COMP_brotli_oneshot(),
COMP_zstd(), and COMP_zstd_oneshot() return a B<COMP_METHOD> on success,
or NULL on failure.