#include <openssl/err.h>
#include "crypto/cryptlib.h"
#include "internal/bio.h"
+#include "internal/thread_once.h"
#include "comp_local.h"
COMP_METHOD *COMP_zlib(void);
static deflateInit__ft p_deflateInit_ = NULL;
static zError__ft p_zError = NULL;
-static int zlib_loaded = 0; /* only attempt to init func pts once */
static DSO *zlib_dso = NULL;
# define compress p_compress
return olen - state->istream.avail_out;
}
-#endif
-
-COMP_METHOD *COMP_zlib(void)
+static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)
{
- COMP_METHOD *meth = &zlib_method_nozlib;
-
-#ifdef ZLIB_SHARED
+# ifdef ZLIB_SHARED
/* LIBZ may be externally defined, and we should respect that value */
-# ifndef LIBZ
-# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
-# define LIBZ "ZLIB1"
-# elif defined(OPENSSL_SYS_VMS)
-# define LIBZ "LIBZ"
-# else
-# define LIBZ "z"
+# ifndef LIBZ
+# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
+# define LIBZ "ZLIB1"
+# elif defined(OPENSSL_SYS_VMS)
+# define LIBZ "LIBZ"
+# else
+# define LIBZ "z"
+# endif
# endif
-# endif
- if (!zlib_loaded) {
- zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
- if (zlib_dso != NULL) {
- p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress");
- 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_deflateEnd
- = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd");
- p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate");
- p_deflateInit_
- = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_");
- p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError");
-
- if (p_compress && p_inflateEnd && p_inflate
- && p_inflateInit_ && p_deflateEnd
- && p_deflate && p_deflateInit_ && p_zError)
- zlib_loaded++;
-
- if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) {
- ossl_comp_zlib_cleanup();
- return meth;
- }
- if (zlib_loaded)
- meth = &zlib_stateful_method;
+ zlib_dso = DSO_load(NULL, LIBZ, NULL, 0);
+ if (zlib_dso != NULL) {
+ p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress");
+ 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_deflateEnd = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd");
+ p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate");
+ 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
+ || p_inflate == NULL || p_inflateInit_ == NULL
+ || p_deflateEnd == NULL || p_deflate == NULL
+ || p_deflateInit_ == NULL || p_zError == NULL) {
+ ossl_comp_zlib_cleanup();
+ return 0;
}
}
+# endif
+ return 1;
+}
#endif
-#if defined(ZLIB)
- meth = &zlib_stateful_method;
+
+COMP_METHOD *COMP_zlib(void)
+{
+ COMP_METHOD *meth = &zlib_method_nozlib;
+
+#ifdef ZLIB
+ if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init))
+ meth = &zlib_stateful_method;
#endif
return meth;
}
+/* Also called from OPENSSL_cleanup() */
void ossl_comp_zlib_cleanup(void)
{
#ifdef ZLIB_SHARED
static int bio_zlib_new(BIO *bi)
{
BIO_ZLIB_CTX *ctx;
+
# ifdef ZLIB_SHARED
- (void)COMP_zlib();
- if (!zlib_loaded) {
+ if (!RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) {
ERR_raise(ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED);
return 0;
}
static int bio_zlib_free(BIO *bi)
{
BIO_ZLIB_CTX *ctx;
+
if (!bi)
return 0;
ctx = BIO_get_data(bi);
static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
BIO *next = BIO_next(b);
+
if (next == NULL)
return 0;
return BIO_callback_ctrl(next, cmd, fp);
# endif
#endif
-#ifndef OPENSSL_NO_COMP
-static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT;
-
-static int zlib_inited = 0;
-DEFINE_RUN_ONCE_STATIC(ossl_init_zlib)
-{
- /* Do nothing - we need to know about this for the later cleanup */
- zlib_inited = 1;
- return 1;
-}
-#endif
-
void OPENSSL_cleanup(void)
{
OPENSSL_INIT_STOP *currhandler, *lasthandler;
*/
#ifndef OPENSSL_NO_COMP
- if (zlib_inited) {
- OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n");
- ossl_comp_zlib_cleanup();
- }
+ OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n");
+ ossl_comp_zlib_cleanup();
#endif
if (async_inited) {
}
#endif
-#ifndef OPENSSL_NO_COMP
- if ((opts & OPENSSL_INIT_ZLIB)
- && !RUN_ONCE(&zlib, ossl_init_zlib))
- return 0;
-#endif
-
if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, init_lock))
return 0;