diff --git a/gnutls-3.8.6-compression-dlwrap.patch b/gnutls-3.8.6-compression-dlwrap.patch new file mode 100644 index 0000000..835f151 --- /dev/null +++ b/gnutls-3.8.6-compression-dlwrap.patch @@ -0,0 +1,2131 @@ +From dd7f8c30ca44695992bbb92146e385b4b700f285 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 29 Jun 2024 09:52:55 +0900 +Subject: [PATCH 1/4] m4: factor out soname check into a separate macro + +This moves the SONAME detection from configure.ac to m4/hooks.m4 as +the LIBGNUTLS_CHECK_SONAME macro. The new macro doesn't implicitly +set *_LIBRARY_SONAME to "none", so the callers need to adjust +themselves depending on whether the macro is defined. + +Signed-off-by: Daiki Ueno +--- + configure.ac | 50 ++++++++++++-------------------------------------- + lib/fips.c | 26 ++++++++++++++------------ + lib/fipshmac.c | 14 ++++++++++++++ + lib/global.c | 6 ++++++ + m4/hooks.m4 | 20 ++++++++++++++++++++ + 5 files changed, 66 insertions(+), 50 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 1744813b79..3f001998b4 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -810,61 +810,35 @@ save_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $GMP_CFLAGS" + save_LIBS=$LIBS + LIBS="$LIBS $GMP_LIBS" +-AC_MSG_CHECKING([gmp soname]) +-AC_LINK_IFELSE([AC_LANG_PROGRAM([ ++LIBGNUTLS_CHECK_SONAME([gmp], [AC_LANG_PROGRAM([ + #include ],[ + mpz_t n; +- mpz_init(n);])], +- [gmp_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libgmp\.so'`], +- [gmp_so=none]) +-if test -z "$gmp_so"; then +- gmp_so=none +-fi +-AC_MSG_RESULT($gmp_so) +-if test "$gmp_so" != none; then +- AC_DEFINE_UNQUOTED([GMP_LIBRARY_SONAME], ["$gmp_so"], [The soname of gmp library]) +-fi +-LIBS=$save_LIBS +-CFLAGS=$save_CFLAGS ++ mpz_init(n);])]) ++LIBS="$save_LIBS" ++CFLAGS="$save_CFLAGS" + + save_CFLAGS=$CFLAGS + CFLAGS="$CFLAGS $NETTLE_CFLAGS" + save_LIBS=$LIBS + LIBS="$LIBS $NETTLE_LIBS" +-AC_MSG_CHECKING([nettle soname]) +-AC_LINK_IFELSE([AC_LANG_PROGRAM([ ++LIBGNUTLS_CHECK_SONAME([nettle], [AC_LANG_PROGRAM([ + #include ],[ + struct sha256_ctx ctx; +- sha256_init(&ctx);])], +- [nettle_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libnettle\.so'`], +- [nettle_so=none]) +-if test -z "$nettle_so"; then +- nettle_so=none +-fi +-AC_MSG_RESULT($nettle_so) +-AC_DEFINE_UNQUOTED([NETTLE_LIBRARY_SONAME], ["$nettle_so"], [The soname of nettle library]) +-LIBS=$save_LIBS +-CFLAGS=$save_CFLAGS ++ sha256_init(&ctx);])]) ++LIBS="$save_LIBS" ++CFLAGS="$save_CFLAGS" + + save_CFLAGS=$CFLAGS + # includes + CFLAGS="$CFLAGS $HOGWEED_CFLAGS $GMP_CFLAGS" + save_LIBS=$LIBS + LIBS="$LIBS $HOGWEED_LIBS" +-AC_MSG_CHECKING([hogweed soname]) +-AC_LINK_IFELSE([AC_LANG_PROGRAM([ ++LIBGNUTLS_CHECK_SONAME([hogweed], [AC_LANG_PROGRAM([ + #include ],[ + struct rsa_private_key priv; +- nettle_rsa_private_key_init(&priv);])], +- [hogweed_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^libhogweed\.so'`], +- [hogweed_so=none]) +-if test -z "$hogweed_so"; then +- hogweed_so=none +-fi +-AC_MSG_RESULT($hogweed_so) +-AC_DEFINE_UNQUOTED([HOGWEED_LIBRARY_SONAME], ["$hogweed_so"], [The soname of hogweed library]) +-LIBS=$save_LIBS +-CFLAGS=$save_CFLAGS ++ nettle_rsa_private_key_init(&priv);])]) ++LIBS="$save_LIBS" ++CFLAGS="$save_CFLAGS" + + gnutls_so=libgnutls.so.`expr "$LT_CURRENT" - "$LT_AGE"` + AC_DEFINE_UNQUOTED([GNUTLS_LIBRARY_SONAME], ["$gnutls_so"], [The soname of gnutls library]) +diff --git a/lib/fips.c b/lib/fips.c +index 1611200be8..e5fce6b1b9 100644 +--- a/lib/fips.c ++++ b/lib/fips.c +@@ -152,15 +152,17 @@ void _gnutls_fips_mode_reset_zombie(void) + } + } + +-/* These only works with the platform where SONAME is part of the ABI. +- * For example, *_SONAME will be set to "none" on Windows platforms. */ +-#define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME +-#define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME +-#define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME ++/* These only works with the platform where SONAME is part of the ABI. */ ++#ifndef GNUTLS_LIBRARY_SONAME ++#define GNUTLS_LIBRARY_SONAME "none" ++#endif + +-/* GMP can be statically linked. */ +-#ifdef GMP_LIBRARY_SONAME +-#define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME ++#ifndef NETTLE_LIBRARY_SONAME ++#define NETTLE_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef HOGWEED_LIBRARY_SONAME ++#define HOGWEED_LIBRARY_SONAME "none" + #endif + + #define HMAC_SIZE 32 +@@ -246,14 +248,14 @@ static int handler(void *user, const char *section, const char *name, + } else { + return 0; + } +- } else if (!strcmp(section, GNUTLS_LIBRARY_NAME)) { ++ } else if (!strcmp(section, GNUTLS_LIBRARY_SONAME)) { + return lib_handler(&p->gnutls, section, name, value); +- } else if (!strcmp(section, NETTLE_LIBRARY_NAME)) { ++ } else if (!strcmp(section, NETTLE_LIBRARY_SONAME)) { + return lib_handler(&p->nettle, section, name, value); +- } else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) { ++ } else if (!strcmp(section, HOGWEED_LIBRARY_SONAME)) { + return lib_handler(&p->hogweed, section, name, value); + #ifdef GMP_LIBRARY_SONAME +- } else if (!strcmp(section, GMP_LIBRARY_NAME)) { ++ } else if (!strcmp(section, GMP_LIBRARY_SONAME)) { + return lib_handler(&p->gmp, section, name, value); + #endif + } else { +diff --git a/lib/fipshmac.c b/lib/fipshmac.c +index 6a4883a131..d3561b4c47 100644 +--- a/lib/fipshmac.c ++++ b/lib/fipshmac.c +@@ -34,6 +34,20 @@ + #include "errors.h" + + #define FORMAT_VERSION 1 ++ ++/* These only works with the platform where SONAME is part of the ABI. */ ++#ifndef GNUTLS_LIBRARY_SONAME ++#define GNUTLS_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef NETTLE_LIBRARY_SONAME ++#define NETTLE_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef HOGWEED_LIBRARY_SONAME ++#define HOGWEED_LIBRARY_SONAME "none" ++#endif ++ + #define HMAC_SIZE 32 + #define HMAC_ALGO GNUTLS_MAC_SHA256 + #define HMAC_STR_SIZE (2 * HMAC_SIZE + 1) +diff --git a/lib/global.c b/lib/global.c +index 718740c103..b434140bbf 100644 +--- a/lib/global.c ++++ b/lib/global.c +@@ -563,9 +563,15 @@ static const struct gnutls_library_config_st _gnutls_library_config[] = { + #ifdef FIPS_MODULE_VERSION + { "fips-module-version", FIPS_MODULE_VERSION }, + #endif ++#ifdef GNUTLS_LIBRARY_SONAME + { "libgnutls-soname", GNUTLS_LIBRARY_SONAME }, ++#endif ++#ifdef NETTLE_LIBRARY_SONAME + { "libnettle-soname", NETTLE_LIBRARY_SONAME }, ++#endif ++#ifdef HOGWEED_LIBRARY_SONAME + { "libhogweed-soname", HOGWEED_LIBRARY_SONAME }, ++#endif + #ifdef GMP_LIBRARY_SONAME + { "libgmp-soname", GMP_LIBRARY_SONAME }, + #endif +diff --git a/m4/hooks.m4 b/m4/hooks.m4 +index cf6064ca1d..a786d35150 100644 +--- a/m4/hooks.m4 ++++ b/m4/hooks.m4 +@@ -421,3 +421,23 @@ dnl #AM_ICONV + dnl m4_ifdef([gl_ICONV_MODULE_INDICATOR], + dnl [gl_ICONV_MODULE_INDICATOR([iconv])]) + ]) ++ ++AC_DEFUN([LIBGNUTLS_CHECK_SONAME], ++[ ++ m4_pushdef([soname], AS_TR_SH([$1])) ++ m4_pushdef([SONAME], AS_TR_CPP([$1])) ++ AC_MSG_CHECKING([$1 [soname]]) ++ AC_LINK_IFELSE([$2], ++ [soname[]_so=`(eval "$LDDPROG conftest$EXEEXT $LDDPOSTPROC") | grep '^lib[]$1\.so'`], ++ [soname[]_so=none]) ++ if test -z "$soname[]_so"; then ++ soname[]_so=none ++ fi ++ AC_MSG_RESULT($soname[]_so) ++ if test "$soname[]_so" != none; then ++ SONAME[]_LIBRARY_SONAME="$soname[]_so" ++ AC_DEFINE_UNQUOTED([SONAME[]_LIBRARY_SONAME], ["$soname[]_so"], [The soname of $1 library]) ++ fi ++ m4_popdef([soname]) ++ m4_popdef([SONAME]) ++]) +-- +2.45.2 + + +From 0647139f50b6c14f2f2d22d40a42a8fdfaead5d5 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 6 Jul 2024 11:59:08 +0900 +Subject: [PATCH 2/4] build: check if dlopen(SONAME) works in configure + +Signed-off-by: Daiki Ueno +--- + configure.ac | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 3f001998b4..8d8c4038b6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -946,6 +946,27 @@ AM_CONDITIONAL(P11KIT_0_23_11_API, $PKG_CONFIG --atleast-version=0.23.11 p11-kit + + AM_CONDITIONAL(ENABLE_PKCS11, test "$with_p11_kit" != "no") + ++save_LIBS=$LIBS ++LIBS="$LIBS -lm" ++LIBGNUTLS_CHECK_SONAME([m], [AC_LANG_PROGRAM([ ++ #include ],[ ++ trunc (0);])]) ++LIBS="$save_LIBS" ++CFLAGS="$save_CFLAGS" ++ ++AC_RUN_IFELSE( ++ [AC_LANG_PROGRAM( ++ [[#include ++ #include ++ ]], ++ [[void *handle = dlopen("$M_LIBRARY_SONAME", RTLD_LAZY | RTLD_GLOBAL); ++ return handle != NULL ? 0 : 1; ++ ]])], ++ [ac_cv_dlopen_soname_works=yes], ++ [ac_cv_dlopen_soname_works=no], ++ [ac_cv_dlopen_soname_works=cross-compiling]) ++ ++AM_CONDITIONAL([ENABLE_DLOPEN], [test "$ac_cv_dlopen_soname_works" = yes]) + need_ltlibdl=no + + AC_ARG_WITH(tpm2, +-- +2.45.2 + + +From 297c83d2830e44a675e8e52d65a66e0ba327f788 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 29 Jun 2024 13:34:36 +0900 +Subject: [PATCH 3/4] build: detect SONAME for compression libraries at + configure + +Instead of hard-coding the SONAMEs for zlib, libzstd, libbrotlienc, +and libbrotlidec, this checks the actual SONAMEs at configure time, so +the first argument of dlopen is more acurate when a SONAME is bumped. + +Signed-off-by: Daiki Ueno +--- + configure.ac | 82 +++++++++++++++++++++++++++++++++++++++----------- + lib/compress.c | 8 ++--- + 2 files changed, 68 insertions(+), 22 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 8d8c4038b6..28d6895efb 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1048,8 +1048,6 @@ AC_DEFINE_UNQUOTED([TROUSERS_LIB], ["$ac_trousers_lib"], [the location of the tr + AC_SUBST(TROUSERS_LIB) + + +-AM_CONDITIONAL(NEED_LTLIBDL, test "$need_ltlibdl" = yes) +- + # For minitasn1. + AC_CHECK_SIZEOF(unsigned long int, 4) + AC_CHECK_SIZEOF(unsigned int, 4) +@@ -1058,35 +1056,45 @@ AC_CHECK_SIZEOF(time_t, 4) + AC_ARG_WITH(zlib, AS_HELP_STRING([--without-zlib], + [disable zlib compression support]), + ac_zlib=$withval, ac_zlib=yes) +-AC_MSG_CHECKING([whether to include zlib compression support]) +-if test x$ac_zlib != xno; then +- AC_MSG_RESULT(yes) +- AC_LIB_HAVE_LINKFLAGS(z,, [#include ], [compress (0, 0, 0, 0);]) +- if test x$ac_cv_libz != xyes; then +- AC_MSG_WARN( +- *** +- *** ZLIB was not found. You will not be able to use ZLIB compression.) +-fi +-else +- AC_MSG_RESULT(no) +-fi +- +-PKG_CHECK_EXISTS(zlib, ZLIB_HAS_PKGCONFIG=y, ZLIB_HAS_PKGCONFIG=n) +- + if test x$ac_zlib != xno; then ++ PKG_CHECK_EXISTS(zlib, ZLIB_HAS_PKGCONFIG=y, ZLIB_HAS_PKGCONFIG=n) + if test "$ZLIB_HAS_PKGCONFIG" = "y" ; then ++ PKG_CHECK_MODULES(ZLIB, [zlib]) + if test "x$GNUTLS_REQUIRES_PRIVATE" = x; then + GNUTLS_REQUIRES_PRIVATE="Requires.private: zlib" + else + GNUTLS_REQUIRES_PRIVATE="$GNUTLS_REQUIRES_PRIVATE, zlib" + fi +- LIBZ_PC="" ++ ac_zlib=yes + else ++ AC_LIB_HAVE_LINKFLAGS(z,, [#include ], [compress (0, 0, 0, 0);]) ++ if test x$ac_cv_libz != xyes; then ++ AC_MSG_WARN([[ ++*** ++*** ZLIB was not found. You will not be able to use ZLIB compression. ++*** ]]) ++ fi ++ ac_zlib=$ac_cv_libz ++ ZLIB_LIBS=$LIBZ + LIBZ_PC=$LIBZ + fi + fi ++if test x$ac_zlib != xno; then ++ AC_DEFINE([HAVE_LIBZ], 1, [Define if ZLIB compression is enabled.]) ++ need_ltlibdl=yes ++fi + AC_SUBST(LIBZ_PC) + ++AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [ ++ save_LIBS=$LIBS ++ LIBS="$LIBS $ZLIB_LIBS" ++ LIBGNUTLS_CHECK_SONAME([z], [AC_LANG_PROGRAM([ ++ #include ],[ ++ compress (0, 0, 0, 0);])]) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++]) ++ + AC_ARG_WITH(brotli, + AS_HELP_STRING([--without-brotli], [disable brotli compression support]), + ac_brotli=$withval, ac_brotli=yes) +@@ -1102,6 +1110,7 @@ if test x$ac_brotli != xno; then + else + GNUTLS_REQUIRES_PRIVATE="${GNUTLS_REQUIRES_PRIVATE}, libbrotlienc, libbrotlidec" + fi ++ need_ltlibdl=yes + else + AC_MSG_WARN(*** LIBBROTLI was not found. You will not be able to use BROTLI compression.) + fi +@@ -1110,6 +1119,28 @@ else + fi + AM_CONDITIONAL(HAVE_LIBBROTLI, test "$with_libbrotlienc" != "no" && test "$with_libbrotlidec" != "no") + ++AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [ ++ save_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS $LIBBROTLIENC_CFLAGS" ++ save_LIBS=$LIBS ++ LIBS="$LIBS $LIBBROTLIENC_LIBS" ++ LIBGNUTLS_CHECK_SONAME([brotlienc], [AC_LANG_PROGRAM([ ++ #include ],[ ++ BrotliEncoderVersion();])]) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++ ++ save_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS $LIBBROTLIDEC_CFLAGS" ++ save_LIBS=$LIBS ++ LIBS="$LIBS $LIBBROTLIDEC_LIBS" ++ LIBGNUTLS_CHECK_SONAME([brotlidec], [AC_LANG_PROGRAM([ ++ #include ],[ ++ BrotliDecoderVersion();])]) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++]) ++ + AC_ARG_WITH(zstd, + AS_HELP_STRING([--without-zstd], [disable zstd compression support]), + ac_zstd=$withval, ac_zstd=yes) +@@ -1124,6 +1155,7 @@ if test x$ac_zstd != xno; then + else + GNUTLS_REQUIRES_PRIVATE="${GNUTLS_REQUIRES_PRIVATE}, libzstd" + fi ++ need_ltlibdl=yes + else + AC_MSG_WARN(*** LIBZSTD was not found. You will not be able to use ZSTD compression.) + fi +@@ -1132,6 +1164,20 @@ else + fi + AM_CONDITIONAL(HAVE_LIBZSTD, test "$with_libzstd" != "no") + ++AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [ ++ save_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS $LIBZSTD_CFLAGS" ++ save_LIBS=$LIBS ++ LIBS="$LIBS $LIBZSTD_LIBS" ++ LIBGNUTLS_CHECK_SONAME([zstd], [AC_LANG_PROGRAM([ ++ #include ],[ ++ ZSTD_versionNumber();])]) ++ LIBS="$save_LIBS" ++ CFLAGS="$save_CFLAGS" ++]) ++ ++AM_CONDITIONAL(NEED_LTLIBDL, test "$need_ltlibdl" = yes) ++ + # export for use in scripts + AC_SUBST(ac_cv_sizeof_time_t) + +diff --git a/lib/compress.c b/lib/compress.c +index a0a7c699c3..26ea2912c2 100644 +--- a/lib/compress.c ++++ b/lib/compress.c +@@ -72,7 +72,7 @@ static int zlib_init(void) + #ifndef _WIN32 + if (_zlib_handle != NULL) + return 0; +- if ((_zlib_handle = dlopen("libz.so.1", RTLD_NOW | RTLD_GLOBAL)) == ++ if ((_zlib_handle = dlopen(Z_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) == + NULL) + goto error; + if ((_gnutls_zlib_compressBound = +@@ -135,10 +135,10 @@ static int brotli_init(void) + #ifndef _WIN32 + if (_brotlienc_handle != NULL || _brotlidec_handle != NULL) + return 0; +- if ((_brotlienc_handle = dlopen("libbrotlienc.so.1", ++ if ((_brotlienc_handle = dlopen(BROTLIENC_LIBRARY_SONAME, + RTLD_NOW | RTLD_GLOBAL)) == NULL) + goto error; +- if ((_brotlidec_handle = dlopen("libbrotlidec.so.1", ++ if ((_brotlidec_handle = dlopen(BROTLIDEC_LIBRARY_SONAME, + RTLD_NOW | RTLD_GLOBAL)) == NULL) + goto error; + if ((_gnutls_BrotliEncoderMaxCompressedSize = +@@ -195,7 +195,7 @@ static int zstd_init(void) + #ifndef _WIN32 + if (_zstd_handle != NULL) + return 0; +- if ((_zstd_handle = dlopen("libzstd.so.1", RTLD_NOW | RTLD_GLOBAL)) == ++ if ((_zstd_handle = dlopen(ZSTD_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) == + NULL) + goto error; + if ((_gnutls_ZSTD_isError = dlsym(_zstd_handle, "ZSTD_isError")) == +-- +2.45.2 + + +From 3e5be1315a15ac6e1e33e08f28030b8215b6d234 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 29 Jun 2024 13:36:58 +0900 +Subject: [PATCH 4/4] build: switch to using dlwrap for loading compression + libraries + +This switches the logic to load compression libraries from the +hand-written code to the automatically generated code by the dlwrap +tool[1], which enables to select whether to use dlopen or link to the +library at build time. + +1. https://crates.io/crates/dlwrap + +Signed-off-by: Daiki Ueno +--- + cfg.mk | 2 +- + configure.ac | 1 + + devel/check-headers.sh | 4 +- + devel/dlwrap/brotli.license | 4 + + devel/dlwrap/brotlidec.syms | 1 + + devel/dlwrap/brotlienc.syms | 2 + + devel/dlwrap/z.license | 20 ++++ + devel/dlwrap/z.syms | 3 + + devel/dlwrap/zstd.license | 7 ++ + devel/dlwrap/zstd.syms | 4 + + devel/generate-dlwrap.sh | 37 ++++++ + devel/indent-gnutls | 2 +- + lib/Makefile.am | 40 ++++++- + lib/compress.c | 218 ++++++++++-------------------------- + lib/dlwrap/brotlidec.c | 182 ++++++++++++++++++++++++++++++ + lib/dlwrap/brotlidec.h | 47 ++++++++ + lib/dlwrap/brotlidecfuncs.h | 9 ++ + lib/dlwrap/brotlienc.c | 182 ++++++++++++++++++++++++++++++ + lib/dlwrap/brotlienc.h | 47 ++++++++ + lib/dlwrap/brotliencfuncs.h | 10 ++ + lib/dlwrap/zlib.c | 182 ++++++++++++++++++++++++++++++ + lib/dlwrap/zlib.h | 47 ++++++++ + lib/dlwrap/zlibfuncs.h | 27 +++++ + lib/dlwrap/zstd.c | 182 ++++++++++++++++++++++++++++++ + lib/dlwrap/zstd.h | 47 ++++++++ + lib/dlwrap/zstdfuncs.h | 15 +++ + 26 files changed, 1154 insertions(+), 168 deletions(-) + create mode 100644 devel/dlwrap/brotli.license + create mode 100644 devel/dlwrap/brotlidec.syms + create mode 100644 devel/dlwrap/brotlienc.syms + create mode 100644 devel/dlwrap/z.license + create mode 100644 devel/dlwrap/z.syms + create mode 100644 devel/dlwrap/zstd.license + create mode 100644 devel/dlwrap/zstd.syms + create mode 100755 devel/generate-dlwrap.sh + create mode 100644 lib/dlwrap/brotlidec.c + create mode 100644 lib/dlwrap/brotlidec.h + create mode 100644 lib/dlwrap/brotlidecfuncs.h + create mode 100644 lib/dlwrap/brotlienc.c + create mode 100644 lib/dlwrap/brotlienc.h + create mode 100644 lib/dlwrap/brotliencfuncs.h + create mode 100644 lib/dlwrap/zlib.c + create mode 100644 lib/dlwrap/zlib.h + create mode 100644 lib/dlwrap/zlibfuncs.h + create mode 100644 lib/dlwrap/zstd.c + create mode 100644 lib/dlwrap/zstd.h + create mode 100644 lib/dlwrap/zstdfuncs.h + +diff --git a/cfg.mk b/cfg.mk +index 5ef839a2c1..1b94279633 100644 +--- a/cfg.mk ++++ b/cfg.mk +@@ -24,7 +24,7 @@ PACKAGE ?= gnutls + + .PHONY: config glimport + +-INDENT_SOURCES = `find . -name \*.[ch] -o -name gnutls.h.in | grep -v -e ^./build-aux/ -e ^./config.h -e ^./devel/ -e ^./gnulib -e ^./lib/minitasn1/ -e ^./lib/includes/gnutls/gnutls.h -e ^./lib/nettle/backport/ -e ^./lib/priority_options.h -e ^./lib/unistring/ -e ^./lib/x509/supported_exts.h -e ^./lib/build-aux/ -e ^./gl/ -e ^./src/gl/ -e ^./src/.*-options.[ch] -e -args.[ch] -e asn1_tab.c -e ^./tests/suite/` ++INDENT_SOURCES = `find . -name \*.[ch] -o -name gnutls.h.in | grep -v -e ^./build-aux/ -e ^./config.h -e ^./devel/ -e ^./gnulib -e ^./lib/minitasn1/ -e ^./lib/includes/gnutls/gnutls.h -e ^./lib/nettle/backport/ -e ^./lib/priority_options.h -e ^./lib/unistring/ -e ^./lib/x509/supported_exts.h -e ^./lib/build-aux/ -e ^./lib/dlwrap/ -e ^./gl/ -e ^./src/gl/ -e ^./src/.*-options.[ch] -e -args.[ch] -e asn1_tab.c -e ^./tests/suite/` + + ifeq ($(.DEFAULT_GOAL),abort-due-to-no-makefile) + .DEFAULT_GOAL := bootstrap +diff --git a/configure.ac b/configure.ac +index 28d6895efb..62a7fbdf66 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1083,6 +1083,7 @@ if test x$ac_zlib != xno; then + AC_DEFINE([HAVE_LIBZ], 1, [Define if ZLIB compression is enabled.]) + need_ltlibdl=yes + fi ++AM_CONDITIONAL(HAVE_ZLIB, test "$ac_zlib" = "yes") + AC_SUBST(LIBZ_PC) + + AS_IF([test "$ac_cv_dlopen_soname_works" = yes], [ +diff --git a/devel/dlwrap/brotli.license b/devel/dlwrap/brotli.license +new file mode 100644 +index 0000000000..d65b39b1ac +--- /dev/null ++++ b/devel/dlwrap/brotli.license +@@ -0,0 +1,4 @@ ++Copyright 2013 Google Inc. All Rights Reserved. ++ ++Distributed under MIT license. ++See file LICENSE for detail or copy at https://opensource.org/licenses/MIT +diff --git a/devel/dlwrap/brotlidec.syms b/devel/dlwrap/brotlidec.syms +new file mode 100644 +index 0000000000..97edbad15e +--- /dev/null ++++ b/devel/dlwrap/brotlidec.syms +@@ -0,0 +1 @@ ++BrotliDecoderDecompress +diff --git a/devel/dlwrap/brotlienc.syms b/devel/dlwrap/brotlienc.syms +new file mode 100644 +index 0000000000..d618292047 +--- /dev/null ++++ b/devel/dlwrap/brotlienc.syms +@@ -0,0 +1,2 @@ ++BrotliEncoderMaxCompressedSize ++BrotliEncoderCompress +diff --git a/devel/dlwrap/z.license b/devel/dlwrap/z.license +new file mode 100644 +index 0000000000..94ce4ae9c9 +--- /dev/null ++++ b/devel/dlwrap/z.license +@@ -0,0 +1,20 @@ ++Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler ++ ++This software is provided 'as-is', without any express or implied ++warranty. In no event will the authors be held liable for any damages ++arising from the use of this software. ++ ++Permission is granted to anyone to use this software for any purpose, ++including commercial applications, and to alter it and redistribute it ++freely, subject to the following restrictions: ++ ++1. The origin of this software must not be misrepresented; you must not ++ claim that you wrote the original software. If you use this software ++ in a product, an acknowledgment in the product documentation would be ++ appreciated but is not required. ++2. Altered source versions must be plainly marked as such, and must not be ++ misrepresented as being the original software. ++3. This notice may not be removed or altered from any source distribution. ++ ++Jean-loup Gailly Mark Adler ++jloup@gzip.org madler@alumni.caltech.edu +diff --git a/devel/dlwrap/z.syms b/devel/dlwrap/z.syms +new file mode 100644 +index 0000000000..e3ed6c13f2 +--- /dev/null ++++ b/devel/dlwrap/z.syms +@@ -0,0 +1,3 @@ ++compressBound ++compress ++uncompress +diff --git a/devel/dlwrap/zstd.license b/devel/dlwrap/zstd.license +new file mode 100644 +index 0000000000..4b585386bf +--- /dev/null ++++ b/devel/dlwrap/zstd.license +@@ -0,0 +1,7 @@ ++Copyright (c) Meta Platforms, Inc. and affiliates. ++All rights reserved. ++ ++This source code is licensed under both the BSD-style license (found in the ++LICENSE file in the root directory of this source tree) and the GPLv2 (found ++in the COPYING file in the root directory of this source tree). ++You may select, at your option, one of the above-listed licenses. +diff --git a/devel/dlwrap/zstd.syms b/devel/dlwrap/zstd.syms +new file mode 100644 +index 0000000000..881bdc8135 +--- /dev/null ++++ b/devel/dlwrap/zstd.syms +@@ -0,0 +1,4 @@ ++ZSTD_isError ++ZSTD_compressBound ++ZSTD_compress ++ZSTD_decompress +diff --git a/devel/generate-dlwrap.sh b/devel/generate-dlwrap.sh +new file mode 100755 +index 0000000000..dbcf870612 +--- /dev/null ++++ b/devel/generate-dlwrap.sh +@@ -0,0 +1,37 @@ ++#!/bin/sh ++ ++# This script generates dlopen stubs for optional libraries using dlwrap tool: ++# https://crates.io/crates/dlwrap ++ ++# Copyright (c) 2023 Daiki Ueno ++# License: GPLv3+ ++ ++set +e ++ ++: ${srcdir=.} ++: ${DLWRAP=dlwrap} ++ ++if ! "$DLWRAP" -V >& /dev/null; then ++ echo 1>&2 "$0: "$DLWRAP" is missing" ++ exit 77 ++fi ++ ++SRC="$srcdir/devel/$DLWRAP" ++DST="$srcdir/lib/$DLWRAP" ++ ++echo "Generating $DST/zlib.h" ++ ++"$DLWRAP" --input /usr/include/zlib.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/z.syms" --license-file "$SRC/z.license" --soname Z_LIBRARY_SONAME --prefix gnutls_zlib --header-guard GNUTLS_LIB_DLWRAP_ZLIB_H_ --include "" ++ ++echo "Generating $DST/zstd.h" ++ ++"$DLWRAP" --input /usr/include/zstd.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/zstd.syms" --license-file "$SRC/zstd.license" --soname ZSTD_LIBRARY_SONAME --prefix gnutls_zstd --header-guard GNUTLS_LIB_DLWRAP_ZSTD_H_ --include "" ++ ++echo "Generating $DST/brotlienc.h" ++ ++"$DLWRAP" --input /usr/include/brotli/encode.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/brotlienc.syms" --license-file "$SRC/brotli.license" --soname BROTLIENC_LIBRARY_SONAME --prefix gnutls_brotlienc --loader-basename brotlienc --header-guard GNUTLS_LIB_DLWRAP_BROTLIENC_H_ --include "" ++ ++echo "Generating $DST/brotlidec.h" ++ ++"$DLWRAP" --input /usr/include/brotli/decode.h -o "$DST" --clang-resource-dir $(clang -print-resource-dir) --symbol-file "$SRC/brotlidec.syms" --license-file "$SRC/brotli.license" --soname BROTLIDEC_LIBRARY_SONAME --prefix gnutls_brotlidec --loader-basename brotlidec --header-guard GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ --include "" ++ +diff --git a/lib/Makefile.am b/lib/Makefile.am +index a50d3114ea..d1bd07248e 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -33,7 +33,7 @@ localedir = $(datadir)/locale + + include $(top_srcdir)/lib/common.mk + +-AM_CPPFLAGS = \ ++AM_CPPFLAGS = \ + -DLOCALEDIR=\"$(localedir)\" \ + -I$(srcdir)/../gl \ + -I$(builddir)/../gl \ +@@ -45,7 +45,8 @@ AM_CPPFLAGS = \ + $(LIBTASN1_CFLAGS) \ + $(P11_KIT_CFLAGS) \ + $(TSS2_CFLAGS) +- $(LIBZSTD_CFLAGS) ++ ++thirdparty_libadd = + + if !HAVE_LIBUNISTRING + SUBDIRS += unistring +@@ -85,6 +86,39 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls + hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \ + iov.c iov.h system/ktls.c system/ktls.h pathbuf.c pathbuf.h + ++if HAVE_ZLIB ++COBJECTS += dlwrap/zlib.c dlwrap/zlibfuncs.h dlwrap/zlib.h ++ ++if ENABLE_DLOPEN ++AM_CPPFLAGS += $(ZLIB_CFLAGS) -DGNUTLS_ZLIB_ENABLE_DLOPEN=1 ++else ++thirdparty_libadd += $(ZLIB_LIBS) ++endif ++endif ++ ++if HAVE_LIBZSTD ++COBJECTS += dlwrap/zstd.c dlwrap/zstdfuncs.h dlwrap/zstd.h ++ ++if ENABLE_DLOPEN ++AM_CPPFLAGS += $(LIBZSTD_CFLAGS) -DGNUTLS_ZSTD_ENABLE_DLOPEN=1 ++else ++thirdparty_libadd += $(LIBZSTD_LIBS) ++endif ++endif ++ ++if HAVE_LIBBROTLI ++COBJECTS += dlwrap/brotlienc.c dlwrap/brotliencfuncs.h dlwrap/brotlienc.h ++COBJECTS += dlwrap/brotlidec.c dlwrap/brotlidecfuncs.h dlwrap/brotlidec.h ++ ++if ENABLE_DLOPEN ++AM_CPPFLAGS += $(LIBBROTLIENC_CFLAGS) -DGNUTLS_BROTLIENC_ENABLE_DLOPEN=1 ++AM_CPPFLAGS += $(LIBBROTLIDEC_CFLAGS) -DGNUTLS_BROTLIDEC_ENABLE_DLOPEN=1 ++else ++thirdparty_libadd += $(LIBBROTLIENC_LIBS) ++thirdparty_libadd += $(LIBBROTLIDEC_LIBS) ++endif ++endif ++ + if ENABLE_GOST + COBJECTS += vko.c + endif +@@ -156,7 +190,7 @@ libgnutls_la_LIBADD = ../gl/libgnu.la x509/libgnutls_x509.la \ + ext/libgnutls_ext.la \ + auth/libgnutls_auth.la algorithms/libgnutls_alg.la \ + extras/libgnutls_extras.la +-thirdparty_libadd = $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \ ++thirdparty_libadd += $(LTLIBINTL) $(LIBSOCKET) $(LTLIBNSL) \ + $(P11_KIT_LIBS) $(LIB_SELECT) $(GNUTLS_LIBS_PRIVATE) + + if HAVE_LIBIDN2 +diff --git a/lib/compress.c b/lib/compress.c +index 26ea2912c2..936a459532 100644 +--- a/lib/compress.c ++++ b/lib/compress.c +@@ -25,198 +25,91 @@ + + #include "compress.h" + +-#ifndef _WIN32 ++#ifdef _WIN32 ++#define RTLD_NOW 0 ++#define RTLD_GLOBAL 0 ++#else + #include + #endif + ++#ifndef Z_LIBRARY_SONAME ++#define Z_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef BROTLIENC_LIBRARY_SONAME ++#define BROTLIENC_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef BROTLIDEC_LIBRARY_SONAME ++#define BROTLIDEC_LIBRARY_SONAME "none" ++#endif ++ ++#ifndef ZSTD_LIBRARY_SONAME ++#define ZSTD_LIBRARY_SONAME "none" ++#endif ++ + #ifdef HAVE_LIBZ +-#include ++#include "dlwrap/zlib.h" + #endif + + #ifdef HAVE_LIBBROTLI +-#include +-#include ++#include "dlwrap/brotlienc.h" ++#include "dlwrap/brotlidec.h" + #endif + + #ifdef HAVE_LIBZSTD +-#include ++#include "dlwrap/zstd.h" + #endif + + #ifdef HAVE_LIBZ +-static void *_zlib_handle; +- +-#if HAVE___TYPEOF__ +-static __typeof__(compressBound)(*_gnutls_zlib_compressBound); +-static __typeof__(compress)(*_gnutls_zlib_compress); +-static __typeof__(uncompress)(*_gnutls_zlib_uncompress); +-#else +-static uLong (*_gnutls_zlib_compressBound)(uLong sourceLen); +-static int (*_gnutls_zlib_compress)(Bytef *dest, uLongf *destLen, +- const Bytef *source, uLong sourceLen); +-static int (*_gnutls_zlib_uncompress)(Bytef *dest, uLongf *destLen, +- const Bytef *source, uLong sourceLen); +-#endif /* HAVE___TYPEOF__ */ +- + static void zlib_deinit(void) + { +-#ifndef _WIN32 +- if (_zlib_handle != NULL) { +- dlclose(_zlib_handle); +- _zlib_handle = NULL; +- } +-#endif /* _WIN32 */ ++ gnutls_zlib_unload_library(); + } + + static int zlib_init(void) + { +-#ifndef _WIN32 +- if (_zlib_handle != NULL) +- return 0; +- if ((_zlib_handle = dlopen(Z_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) == +- NULL) +- goto error; +- if ((_gnutls_zlib_compressBound = +- dlsym(_zlib_handle, "compressBound")) == NULL) +- goto error; +- if ((_gnutls_zlib_compress = dlsym(_zlib_handle, "compress")) == NULL) +- goto error; +- if ((_gnutls_zlib_uncompress = dlsym(_zlib_handle, "uncompress")) == +- NULL) +- goto error; ++ if (gnutls_zlib_ensure_library(Z_LIBRARY_SONAME, ++ RTLD_NOW | RTLD_GLOBAL) < 0) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + return 0; +-error: +- zlib_deinit(); +- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); +-#else +- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); +-#endif /* _WIN32 */ + } + #endif /* HAVE_LIBZ */ + + #ifdef HAVE_LIBBROTLI +-static void *_brotlienc_handle; +-static void *_brotlidec_handle; +- +-#if HAVE___TYPEOF__ +-static __typeof__(BrotliEncoderMaxCompressedSize)( +- *_gnutls_BrotliEncoderMaxCompressedSize); +-static __typeof__(BrotliEncoderCompress)(*_gnutls_BrotliEncoderCompress); +-static __typeof__(BrotliDecoderDecompress)(*_gnutls_BrotliDecoderDecompress); +-#else +-static size_t (*_gnutls_BrotliEncoderMaxCompressedSize)(size_t input_size); +-static BROTLI_BOOL (*_gnutls_BrotliEncoderCompress)( +- int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, +- const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)], +- size_t *encoded_size, +- uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]); +-static BrotliDecoderResult (*_gnutls_BrotliDecoderDecompress)( +- size_t encoded_size, +- const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)], +- size_t *decoded_size, +- uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]); +-#endif /* HAVE___TYPEOF__ */ + + static void brotli_deinit(void) + { +-#ifndef _WIN32 +- if (_brotlienc_handle != NULL) { +- dlclose(_brotlienc_handle); +- _brotlienc_handle = NULL; +- } +- if (_brotlidec_handle != NULL) { +- dlclose(_brotlidec_handle); +- _brotlidec_handle = NULL; +- } +-#endif /* _WIN32 */ ++ gnutls_brotlienc_unload_library(); ++ gnutls_brotlidec_unload_library(); + } + + static int brotli_init(void) + { +-#ifndef _WIN32 +- if (_brotlienc_handle != NULL || _brotlidec_handle != NULL) +- return 0; +- if ((_brotlienc_handle = dlopen(BROTLIENC_LIBRARY_SONAME, +- RTLD_NOW | RTLD_GLOBAL)) == NULL) +- goto error; +- if ((_brotlidec_handle = dlopen(BROTLIDEC_LIBRARY_SONAME, +- RTLD_NOW | RTLD_GLOBAL)) == NULL) +- goto error; +- if ((_gnutls_BrotliEncoderMaxCompressedSize = +- dlsym(_brotlienc_handle, +- "BrotliEncoderMaxCompressedSize")) == NULL) +- goto error; +- if ((_gnutls_BrotliEncoderCompress = +- dlsym(_brotlienc_handle, "BrotliEncoderCompress")) == NULL) +- goto error; +- if ((_gnutls_BrotliDecoderDecompress = dlsym( +- _brotlidec_handle, "BrotliDecoderDecompress")) == NULL) +- goto error; ++ if (gnutls_brotlienc_ensure_library(BROTLIENC_LIBRARY_SONAME, ++ RTLD_NOW | RTLD_GLOBAL) < 0) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ ++ if (gnutls_brotlidec_ensure_library(BROTLIDEC_LIBRARY_SONAME, ++ RTLD_NOW | RTLD_GLOBAL) < 0) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + return 0; +-error: +- brotli_deinit(); +- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); +-#else +- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); +-#endif /* _WIN32 */ + } + #endif /* HAVE_LIBBROTLI */ + + #ifdef HAVE_LIBZSTD +-static void *_zstd_handle; +- +-#if HAVE___TYPEOF__ +-static __typeof__(ZSTD_isError)(*_gnutls_ZSTD_isError); +-static __typeof__(ZSTD_compressBound)(*_gnutls_ZSTD_compressBound); +-static __typeof__(ZSTD_compress)(*_gnutls_ZSTD_compress); +-static __typeof__(ZSTD_decompress)(*_gnutls_ZSTD_decompress); +-#else +-static unsigned (*_gnutls_ZSTD_isError)(size_t code); +-static size_t (*_gnutls_ZSTD_compressBound)(size_t srcSize); +-static size_t (*_gnutls_ZSTD_compress)(void *dst, size_t dstCapacity, +- const void *src, size_t srcSize, +- int compressionLevel); +-static size_t (*_gnutls_ZSTD_decompress)(void *dst, size_t dstCapacity, +- const void *src, +- size_t compressedSize); +-#endif /* HAVE___TYPEOF__ */ + + static void zstd_deinit(void) + { +-#ifndef _WIN32 +- if (_zstd_handle != NULL) { +- dlclose(_zstd_handle); +- _zstd_handle = NULL; +- } +-#endif /* _WIN32 */ ++ gnutls_zstd_unload_library(); + } + + static int zstd_init(void) + { +-#ifndef _WIN32 +- if (_zstd_handle != NULL) +- return 0; +- if ((_zstd_handle = dlopen(ZSTD_LIBRARY_SONAME, RTLD_NOW | RTLD_GLOBAL)) == +- NULL) +- goto error; +- if ((_gnutls_ZSTD_isError = dlsym(_zstd_handle, "ZSTD_isError")) == +- NULL) +- goto error; +- if ((_gnutls_ZSTD_compressBound = +- dlsym(_zstd_handle, "ZSTD_compressBound")) == NULL) +- goto error; +- if ((_gnutls_ZSTD_compress = dlsym(_zstd_handle, "ZSTD_compress")) == +- NULL) +- goto error; +- if ((_gnutls_ZSTD_decompress = +- dlsym(_zstd_handle, "ZSTD_decompress")) == NULL) +- goto error; ++ if (gnutls_zstd_ensure_library(ZSTD_LIBRARY_SONAME, ++ RTLD_NOW | RTLD_GLOBAL) < 0) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + return 0; +-error: +- zstd_deinit(); +- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); +-#else +- return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE); +-#endif /* _WIN32 */ + } + #endif /* HAVE_LIBZSTD */ + +@@ -345,15 +238,16 @@ size_t _gnutls_compress_bound(gnutls_compression_method_t alg, size_t src_len) + switch (alg) { + #ifdef HAVE_LIBZ + case GNUTLS_COMP_ZLIB: +- return _gnutls_zlib_compressBound(src_len); ++ return GNUTLS_ZLIB_FUNC(compressBound)(src_len); + #endif + #ifdef HAVE_LIBBROTLI + case GNUTLS_COMP_BROTLI: +- return _gnutls_BrotliEncoderMaxCompressedSize(src_len); ++ return GNUTLS_BROTLIENC_FUNC(BrotliEncoderMaxCompressedSize)( ++ src_len); + #endif + #ifdef HAVE_LIBZSTD + case GNUTLS_COMP_ZSTD: +- return _gnutls_ZSTD_compressBound(src_len); ++ return GNUTLS_ZSTD_FUNC(ZSTD_compressBound)(src_len); + #endif + default: + return 0; +@@ -372,7 +266,7 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst, + int err; + uLongf comp_len = dst_len; + +- err = _gnutls_zlib_compress(dst, &comp_len, src, src_len); ++ err = GNUTLS_ZLIB_FUNC(compress)(dst, &comp_len, src, src_len); + if (err != Z_OK) + return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED); + ret = comp_len; +@@ -383,7 +277,7 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst, + BROTLI_BOOL err; + size_t comp_len = dst_len; + +- err = _gnutls_BrotliEncoderCompress( ++ err = GNUTLS_BROTLIENC_FUNC(BrotliEncoderCompress)( + BROTLI_DEFAULT_QUALITY, BROTLI_DEFAULT_WINDOW, + BROTLI_DEFAULT_MODE, src_len, src, &comp_len, dst); + if (!err) +@@ -395,9 +289,9 @@ int _gnutls_compress(gnutls_compression_method_t alg, uint8_t *dst, + case GNUTLS_COMP_ZSTD: { + size_t comp_len; + +- comp_len = _gnutls_ZSTD_compress(dst, dst_len, src, src_len, +- ZSTD_CLEVEL_DEFAULT); +- if (_gnutls_ZSTD_isError(comp_len)) ++ comp_len = GNUTLS_ZSTD_FUNC(ZSTD_compress)( ++ dst, dst_len, src, src_len, ZSTD_CLEVEL_DEFAULT); ++ if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(comp_len)) + return gnutls_assert_val(GNUTLS_E_COMPRESSION_FAILED); + ret = comp_len; + } break; +@@ -425,7 +319,8 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst, + int err; + uLongf plain_len = dst_len; + +- err = _gnutls_zlib_uncompress(dst, &plain_len, src, src_len); ++ err = GNUTLS_ZLIB_FUNC(uncompress)(dst, &plain_len, src, ++ src_len); + if (err != Z_OK) + return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); + ret = plain_len; +@@ -436,8 +331,8 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst, + BrotliDecoderResult err; + size_t plain_len = dst_len; + +- err = _gnutls_BrotliDecoderDecompress(src_len, src, &plain_len, +- dst); ++ err = GNUTLS_BROTLIDEC_FUNC( ++ BrotliDecoderDecompress)(src_len, src, &plain_len, dst); + if (err != BROTLI_DECODER_RESULT_SUCCESS) + return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); + ret = plain_len; +@@ -447,8 +342,9 @@ int _gnutls_decompress(gnutls_compression_method_t alg, uint8_t *dst, + case GNUTLS_COMP_ZSTD: { + size_t plain_len; + +- plain_len = _gnutls_ZSTD_decompress(dst, dst_len, src, src_len); +- if (_gnutls_ZSTD_isError(plain_len)) ++ plain_len = GNUTLS_ZSTD_FUNC(ZSTD_decompress)(dst, dst_len, src, ++ src_len); ++ if (GNUTLS_ZSTD_FUNC(ZSTD_isError)(plain_len)) + return gnutls_assert_val(GNUTLS_E_DECOMPRESSION_FAILED); + ret = plain_len; + } break; +diff --git a/lib/dlwrap/brotlidec.c b/lib/dlwrap/brotlidec.c +new file mode 100644 +index 0000000000..45c9b4b259 +--- /dev/null ++++ b/lib/dlwrap/brotlidec.c +@@ -0,0 +1,182 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "brotlidec.h" ++ ++#if defined(GNUTLS_BROTLIDEC_ENABLE_DLOPEN) && GNUTLS_BROTLIDEC_ENABLE_DLOPEN ++ ++#include ++#include ++#include ++#include ++ ++/* If BROTLIDEC_LIBRARY_SONAME is defined, dlopen handle can be automatically ++ * set; otherwise, the caller needs to call ++ * gnutls_brotlidec_ensure_library with soname determined at run time. ++ */ ++#ifdef BROTLIDEC_LIBRARY_SONAME ++ ++static void ++ensure_library (void) ++{ ++ if (gnutls_brotlidec_ensure_library (BROTLIDEC_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0) ++ abort (); ++} ++ ++#if defined(GNUTLS_BROTLIDEC_ENABLE_PTHREAD) && GNUTLS_BROTLIDEC_ENABLE_PTHREAD ++#include ++ ++static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT; ++ ++#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library) ++ ++#else /* GNUTLS_BROTLIDEC_ENABLE_PTHREAD */ ++ ++#define ENSURE_LIBRARY do { \ ++ if (!gnutls_brotlidec_dlhandle) \ ++ ensure_library(); \ ++ } while (0) ++ ++#endif /* !GNUTLS_BROTLIDEC_ENABLE_PTHREAD */ ++ ++#else /* BROTLIDEC_LIBRARY_SONAME */ ++ ++#define ENSURE_LIBRARY do {} while (0) ++ ++#endif /* !BROTLIDEC_LIBRARY_SONAME */ ++ ++static void *gnutls_brotlidec_dlhandle; ++ ++/* Define redirection symbols */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#if (2 <= __GNUC__ || (4 <= __clang_major__)) ++#define FUNC(ret, name, args, cargs) \ ++ static __typeof__(name)(*gnutls_brotlidec_sym_##name); ++#else ++#define FUNC(ret, name, args, cargs) \ ++ static ret(*gnutls_brotlidec_sym_##name)args; ++#endif ++#define VOID_FUNC FUNC ++#include "brotlidecfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++/* Define redirection wrapper functions */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ret gnutls_brotlidec_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_brotlidec_sym_##name); \ ++ return gnutls_brotlidec_sym_##name cargs; \ ++} ++#define VOID_FUNC(ret, name, args, cargs) \ ++ret gnutls_brotlidec_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_brotlidec_sym_##name); \ ++ gnutls_brotlidec_sym_##name cargs; \ ++} ++#include "brotlidecfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++static int ++ensure_symbol (const char *name, void **symp) ++{ ++ if (!*symp) ++ { ++ void *sym = dlsym (gnutls_brotlidec_dlhandle, name); ++ if (!sym) ++ return -errno; ++ *symp = sym; ++ } ++ return 0; ++} ++ ++int ++gnutls_brotlidec_ensure_library (const char *soname, int flags) ++{ ++ int err; ++ ++ if (!gnutls_brotlidec_dlhandle) ++ { ++ gnutls_brotlidec_dlhandle = dlopen (soname, flags); ++ if (!gnutls_brotlidec_dlhandle) ++ return -errno; ++ } ++ ++#define ENSURE_SYMBOL(name) \ ++ ensure_symbol(#name, (void **)&gnutls_brotlidec_sym_##name) ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ err = ENSURE_SYMBOL(name); \ ++ if (err < 0) \ ++ return err; ++#define VOID_FUNC FUNC ++#include "brotlidecfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef ENSURE_SYMBOL ++ return 0; ++} ++ ++void ++gnutls_brotlidec_unload_library (void) ++{ ++ if (gnutls_brotlidec_dlhandle) ++ dlclose (gnutls_brotlidec_dlhandle); ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ gnutls_brotlidec_sym_##name = NULL; ++#define VOID_FUNC FUNC ++#include "brotlidecfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef RESET_SYMBOL ++} ++ ++#else /* GNUTLS_BROTLIDEC_ENABLE_DLOPEN */ ++ ++int ++gnutls_brotlidec_ensure_library (const char *soname, int flags) ++{ ++ (void) soname; ++ (void) flags; ++ return 0; ++} ++ ++void ++gnutls_brotlidec_unload_library (void) ++{ ++} ++ ++#endif /* !GNUTLS_BROTLIDEC_ENABLE_DLOPEN */ +diff --git a/lib/dlwrap/brotlidec.h b/lib/dlwrap/brotlidec.h +new file mode 100644 +index 0000000000..31397f24cf +--- /dev/null ++++ b/lib/dlwrap/brotlidec.h +@@ -0,0 +1,47 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifndef GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ ++#define GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ ++ ++#include ++ ++#if defined(GNUTLS_BROTLIDEC_ENABLE_DLOPEN) && GNUTLS_BROTLIDEC_ENABLE_DLOPEN ++ ++#define FUNC(ret, name, args, cargs) \ ++ ret gnutls_brotlidec_func_##name args; ++#define VOID_FUNC FUNC ++#include "brotlidecfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#define GNUTLS_BROTLIDEC_FUNC(name) gnutls_brotlidec_func_##name ++ ++#else ++ ++#define GNUTLS_BROTLIDEC_FUNC(name) name ++ ++#endif /* GNUTLS_BROTLIDEC_ENABLE_DLOPEN */ ++ ++/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary ++ * symbols are resolved. ++ * ++ * Returns 0 on success; negative error code otherwise. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++int gnutls_brotlidec_ensure_library (const char *soname, int flags); ++ ++/* Unload library and reset symbols. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++void gnutls_brotlidec_unload_library (void); ++ ++#endif /* GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ */ +diff --git a/lib/dlwrap/brotlidecfuncs.h b/lib/dlwrap/brotlidecfuncs.h +new file mode 100644 +index 0000000000..aa033e3a8b +--- /dev/null ++++ b/lib/dlwrap/brotlidecfuncs.h +@@ -0,0 +1,9 @@ ++/* ++ * This file was automatically generated from decode.h, ++ * which is covered by the following license: ++ * Copyright 2013 Google Inc. All Rights Reserved. ++ * ++ * Distributed under MIT license. ++ * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT ++ */ ++FUNC(BrotliDecoderResult, BrotliDecoderDecompress, (size_t encoded_size, const uint8_t encoded_buffer[], size_t *decoded_size, uint8_t decoded_buffer[]), (encoded_size, encoded_buffer, decoded_size, decoded_buffer)) +diff --git a/lib/dlwrap/brotlienc.c b/lib/dlwrap/brotlienc.c +new file mode 100644 +index 0000000000..9dd8ff37c6 +--- /dev/null ++++ b/lib/dlwrap/brotlienc.c +@@ -0,0 +1,182 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "brotlienc.h" ++ ++#if defined(GNUTLS_BROTLIENC_ENABLE_DLOPEN) && GNUTLS_BROTLIENC_ENABLE_DLOPEN ++ ++#include ++#include ++#include ++#include ++ ++/* If BROTLIENC_LIBRARY_SONAME is defined, dlopen handle can be automatically ++ * set; otherwise, the caller needs to call ++ * gnutls_brotlienc_ensure_library with soname determined at run time. ++ */ ++#ifdef BROTLIENC_LIBRARY_SONAME ++ ++static void ++ensure_library (void) ++{ ++ if (gnutls_brotlienc_ensure_library (BROTLIENC_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0) ++ abort (); ++} ++ ++#if defined(GNUTLS_BROTLIENC_ENABLE_PTHREAD) && GNUTLS_BROTLIENC_ENABLE_PTHREAD ++#include ++ ++static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT; ++ ++#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library) ++ ++#else /* GNUTLS_BROTLIENC_ENABLE_PTHREAD */ ++ ++#define ENSURE_LIBRARY do { \ ++ if (!gnutls_brotlienc_dlhandle) \ ++ ensure_library(); \ ++ } while (0) ++ ++#endif /* !GNUTLS_BROTLIENC_ENABLE_PTHREAD */ ++ ++#else /* BROTLIENC_LIBRARY_SONAME */ ++ ++#define ENSURE_LIBRARY do {} while (0) ++ ++#endif /* !BROTLIENC_LIBRARY_SONAME */ ++ ++static void *gnutls_brotlienc_dlhandle; ++ ++/* Define redirection symbols */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#if (2 <= __GNUC__ || (4 <= __clang_major__)) ++#define FUNC(ret, name, args, cargs) \ ++ static __typeof__(name)(*gnutls_brotlienc_sym_##name); ++#else ++#define FUNC(ret, name, args, cargs) \ ++ static ret(*gnutls_brotlienc_sym_##name)args; ++#endif ++#define VOID_FUNC FUNC ++#include "brotliencfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++/* Define redirection wrapper functions */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ret gnutls_brotlienc_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_brotlienc_sym_##name); \ ++ return gnutls_brotlienc_sym_##name cargs; \ ++} ++#define VOID_FUNC(ret, name, args, cargs) \ ++ret gnutls_brotlienc_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_brotlienc_sym_##name); \ ++ gnutls_brotlienc_sym_##name cargs; \ ++} ++#include "brotliencfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++static int ++ensure_symbol (const char *name, void **symp) ++{ ++ if (!*symp) ++ { ++ void *sym = dlsym (gnutls_brotlienc_dlhandle, name); ++ if (!sym) ++ return -errno; ++ *symp = sym; ++ } ++ return 0; ++} ++ ++int ++gnutls_brotlienc_ensure_library (const char *soname, int flags) ++{ ++ int err; ++ ++ if (!gnutls_brotlienc_dlhandle) ++ { ++ gnutls_brotlienc_dlhandle = dlopen (soname, flags); ++ if (!gnutls_brotlienc_dlhandle) ++ return -errno; ++ } ++ ++#define ENSURE_SYMBOL(name) \ ++ ensure_symbol(#name, (void **)&gnutls_brotlienc_sym_##name) ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ err = ENSURE_SYMBOL(name); \ ++ if (err < 0) \ ++ return err; ++#define VOID_FUNC FUNC ++#include "brotliencfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef ENSURE_SYMBOL ++ return 0; ++} ++ ++void ++gnutls_brotlienc_unload_library (void) ++{ ++ if (gnutls_brotlienc_dlhandle) ++ dlclose (gnutls_brotlienc_dlhandle); ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ gnutls_brotlienc_sym_##name = NULL; ++#define VOID_FUNC FUNC ++#include "brotliencfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef RESET_SYMBOL ++} ++ ++#else /* GNUTLS_BROTLIENC_ENABLE_DLOPEN */ ++ ++int ++gnutls_brotlienc_ensure_library (const char *soname, int flags) ++{ ++ (void) soname; ++ (void) flags; ++ return 0; ++} ++ ++void ++gnutls_brotlienc_unload_library (void) ++{ ++} ++ ++#endif /* !GNUTLS_BROTLIENC_ENABLE_DLOPEN */ +diff --git a/lib/dlwrap/brotlienc.h b/lib/dlwrap/brotlienc.h +new file mode 100644 +index 0000000000..ed1af45e04 +--- /dev/null ++++ b/lib/dlwrap/brotlienc.h +@@ -0,0 +1,47 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifndef GNUTLS_LIB_DLWRAP_BROTLIENC_H_ ++#define GNUTLS_LIB_DLWRAP_BROTLIENC_H_ ++ ++#include ++ ++#if defined(GNUTLS_BROTLIENC_ENABLE_DLOPEN) && GNUTLS_BROTLIENC_ENABLE_DLOPEN ++ ++#define FUNC(ret, name, args, cargs) \ ++ ret gnutls_brotlienc_func_##name args; ++#define VOID_FUNC FUNC ++#include "brotliencfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#define GNUTLS_BROTLIENC_FUNC(name) gnutls_brotlienc_func_##name ++ ++#else ++ ++#define GNUTLS_BROTLIENC_FUNC(name) name ++ ++#endif /* GNUTLS_BROTLIENC_ENABLE_DLOPEN */ ++ ++/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary ++ * symbols are resolved. ++ * ++ * Returns 0 on success; negative error code otherwise. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++int gnutls_brotlienc_ensure_library (const char *soname, int flags); ++ ++/* Unload library and reset symbols. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++void gnutls_brotlienc_unload_library (void); ++ ++#endif /* GNUTLS_LIB_DLWRAP_BROTLIENC_H_ */ +diff --git a/lib/dlwrap/brotliencfuncs.h b/lib/dlwrap/brotliencfuncs.h +new file mode 100644 +index 0000000000..1a4f884d35 +--- /dev/null ++++ b/lib/dlwrap/brotliencfuncs.h +@@ -0,0 +1,10 @@ ++/* ++ * This file was automatically generated from encode.h, ++ * which is covered by the following license: ++ * Copyright 2013 Google Inc. All Rights Reserved. ++ * ++ * Distributed under MIT license. ++ * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT ++ */ ++FUNC(size_t, BrotliEncoderMaxCompressedSize, (size_t input_size), (input_size)) ++FUNC(int, BrotliEncoderCompress, (int quality, int lgwin, BrotliEncoderMode mode, size_t input_size, const uint8_t input_buffer[], size_t *encoded_size, uint8_t encoded_buffer[]), (quality, lgwin, mode, input_size, input_buffer, encoded_size, encoded_buffer)) +diff --git a/lib/dlwrap/zlib.c b/lib/dlwrap/zlib.c +new file mode 100644 +index 0000000000..455485c63f +--- /dev/null ++++ b/lib/dlwrap/zlib.c +@@ -0,0 +1,182 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "zlib.h" ++ ++#if defined(GNUTLS_ZLIB_ENABLE_DLOPEN) && GNUTLS_ZLIB_ENABLE_DLOPEN ++ ++#include ++#include ++#include ++#include ++ ++/* If Z_LIBRARY_SONAME is defined, dlopen handle can be automatically ++ * set; otherwise, the caller needs to call ++ * gnutls_zlib_ensure_library with soname determined at run time. ++ */ ++#ifdef Z_LIBRARY_SONAME ++ ++static void ++ensure_library (void) ++{ ++ if (gnutls_zlib_ensure_library (Z_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0) ++ abort (); ++} ++ ++#if defined(GNUTLS_ZLIB_ENABLE_PTHREAD) && GNUTLS_ZLIB_ENABLE_PTHREAD ++#include ++ ++static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT; ++ ++#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library) ++ ++#else /* GNUTLS_ZLIB_ENABLE_PTHREAD */ ++ ++#define ENSURE_LIBRARY do { \ ++ if (!gnutls_zlib_dlhandle) \ ++ ensure_library(); \ ++ } while (0) ++ ++#endif /* !GNUTLS_ZLIB_ENABLE_PTHREAD */ ++ ++#else /* Z_LIBRARY_SONAME */ ++ ++#define ENSURE_LIBRARY do {} while (0) ++ ++#endif /* !Z_LIBRARY_SONAME */ ++ ++static void *gnutls_zlib_dlhandle; ++ ++/* Define redirection symbols */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#if (2 <= __GNUC__ || (4 <= __clang_major__)) ++#define FUNC(ret, name, args, cargs) \ ++ static __typeof__(name)(*gnutls_zlib_sym_##name); ++#else ++#define FUNC(ret, name, args, cargs) \ ++ static ret(*gnutls_zlib_sym_##name)args; ++#endif ++#define VOID_FUNC FUNC ++#include "zlibfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++/* Define redirection wrapper functions */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ret gnutls_zlib_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_zlib_sym_##name); \ ++ return gnutls_zlib_sym_##name cargs; \ ++} ++#define VOID_FUNC(ret, name, args, cargs) \ ++ret gnutls_zlib_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_zlib_sym_##name); \ ++ gnutls_zlib_sym_##name cargs; \ ++} ++#include "zlibfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++static int ++ensure_symbol (const char *name, void **symp) ++{ ++ if (!*symp) ++ { ++ void *sym = dlsym (gnutls_zlib_dlhandle, name); ++ if (!sym) ++ return -errno; ++ *symp = sym; ++ } ++ return 0; ++} ++ ++int ++gnutls_zlib_ensure_library (const char *soname, int flags) ++{ ++ int err; ++ ++ if (!gnutls_zlib_dlhandle) ++ { ++ gnutls_zlib_dlhandle = dlopen (soname, flags); ++ if (!gnutls_zlib_dlhandle) ++ return -errno; ++ } ++ ++#define ENSURE_SYMBOL(name) \ ++ ensure_symbol(#name, (void **)&gnutls_zlib_sym_##name) ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ err = ENSURE_SYMBOL(name); \ ++ if (err < 0) \ ++ return err; ++#define VOID_FUNC FUNC ++#include "zlibfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef ENSURE_SYMBOL ++ return 0; ++} ++ ++void ++gnutls_zlib_unload_library (void) ++{ ++ if (gnutls_zlib_dlhandle) ++ dlclose (gnutls_zlib_dlhandle); ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ gnutls_zlib_sym_##name = NULL; ++#define VOID_FUNC FUNC ++#include "zlibfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef RESET_SYMBOL ++} ++ ++#else /* GNUTLS_ZLIB_ENABLE_DLOPEN */ ++ ++int ++gnutls_zlib_ensure_library (const char *soname, int flags) ++{ ++ (void) soname; ++ (void) flags; ++ return 0; ++} ++ ++void ++gnutls_zlib_unload_library (void) ++{ ++} ++ ++#endif /* !GNUTLS_ZLIB_ENABLE_DLOPEN */ +diff --git a/lib/dlwrap/zlib.h b/lib/dlwrap/zlib.h +new file mode 100644 +index 0000000000..a9666d27f5 +--- /dev/null ++++ b/lib/dlwrap/zlib.h +@@ -0,0 +1,47 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifndef GNUTLS_LIB_DLWRAP_ZLIB_H_ ++#define GNUTLS_LIB_DLWRAP_ZLIB_H_ ++ ++#include ++ ++#if defined(GNUTLS_ZLIB_ENABLE_DLOPEN) && GNUTLS_ZLIB_ENABLE_DLOPEN ++ ++#define FUNC(ret, name, args, cargs) \ ++ ret gnutls_zlib_func_##name args; ++#define VOID_FUNC FUNC ++#include "zlibfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#define GNUTLS_ZLIB_FUNC(name) gnutls_zlib_func_##name ++ ++#else ++ ++#define GNUTLS_ZLIB_FUNC(name) name ++ ++#endif /* GNUTLS_ZLIB_ENABLE_DLOPEN */ ++ ++/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary ++ * symbols are resolved. ++ * ++ * Returns 0 on success; negative error code otherwise. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++int gnutls_zlib_ensure_library (const char *soname, int flags); ++ ++/* Unload library and reset symbols. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++void gnutls_zlib_unload_library (void); ++ ++#endif /* GNUTLS_LIB_DLWRAP_ZLIB_H_ */ +diff --git a/lib/dlwrap/zlibfuncs.h b/lib/dlwrap/zlibfuncs.h +new file mode 100644 +index 0000000000..efe01455d2 +--- /dev/null ++++ b/lib/dlwrap/zlibfuncs.h +@@ -0,0 +1,27 @@ ++/* ++ * This file was automatically generated from zlib.h, ++ * which is covered by the following license: ++ * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler ++ * ++ * This software is provided 'as-is', without any express or implied ++ * warranty. In no event will the authors be held liable for any damages ++ * arising from the use of this software. ++ * ++ * Permission is granted to anyone to use this software for any purpose, ++ * including commercial applications, and to alter it and redistribute it ++ * freely, subject to the following restrictions: ++ * ++ * 1. The origin of this software must not be misrepresented; you must not ++ * claim that you wrote the original software. If you use this software ++ * in a product, an acknowledgment in the product documentation would be ++ * appreciated but is not required. ++ * 2. Altered source versions must be plainly marked as such, and must not be ++ * misrepresented as being the original software. ++ * 3. This notice may not be removed or altered from any source distribution. ++ * ++ * Jean-loup Gailly Mark Adler ++ * jloup@gzip.org madler@alumni.caltech.edu ++ */ ++FUNC(int, compress, (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen), (dest, destLen, source, sourceLen)) ++FUNC(uLong, compressBound, (uLong sourceLen), (sourceLen)) ++FUNC(int, uncompress, (Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen), (dest, destLen, source, sourceLen)) +diff --git a/lib/dlwrap/zstd.c b/lib/dlwrap/zstd.c +new file mode 100644 +index 0000000000..2ea7252975 +--- /dev/null ++++ b/lib/dlwrap/zstd.c +@@ -0,0 +1,182 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "zstd.h" ++ ++#if defined(GNUTLS_ZSTD_ENABLE_DLOPEN) && GNUTLS_ZSTD_ENABLE_DLOPEN ++ ++#include ++#include ++#include ++#include ++ ++/* If ZSTD_LIBRARY_SONAME is defined, dlopen handle can be automatically ++ * set; otherwise, the caller needs to call ++ * gnutls_zstd_ensure_library with soname determined at run time. ++ */ ++#ifdef ZSTD_LIBRARY_SONAME ++ ++static void ++ensure_library (void) ++{ ++ if (gnutls_zstd_ensure_library (ZSTD_LIBRARY_SONAME, RTLD_LAZY | RTLD_LOCAL) < 0) ++ abort (); ++} ++ ++#if defined(GNUTLS_ZSTD_ENABLE_PTHREAD) && GNUTLS_ZSTD_ENABLE_PTHREAD ++#include ++ ++static pthread_once_t dlopen_once = PTHREAD_ONCE_INIT; ++ ++#define ENSURE_LIBRARY pthread_once(&dlopen_once, ensure_library) ++ ++#else /* GNUTLS_ZSTD_ENABLE_PTHREAD */ ++ ++#define ENSURE_LIBRARY do { \ ++ if (!gnutls_zstd_dlhandle) \ ++ ensure_library(); \ ++ } while (0) ++ ++#endif /* !GNUTLS_ZSTD_ENABLE_PTHREAD */ ++ ++#else /* ZSTD_LIBRARY_SONAME */ ++ ++#define ENSURE_LIBRARY do {} while (0) ++ ++#endif /* !ZSTD_LIBRARY_SONAME */ ++ ++static void *gnutls_zstd_dlhandle; ++ ++/* Define redirection symbols */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#if (2 <= __GNUC__ || (4 <= __clang_major__)) ++#define FUNC(ret, name, args, cargs) \ ++ static __typeof__(name)(*gnutls_zstd_sym_##name); ++#else ++#define FUNC(ret, name, args, cargs) \ ++ static ret(*gnutls_zstd_sym_##name)args; ++#endif ++#define VOID_FUNC FUNC ++#include "zstdfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++/* Define redirection wrapper functions */ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ret gnutls_zstd_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_zstd_sym_##name); \ ++ return gnutls_zstd_sym_##name cargs; \ ++} ++#define VOID_FUNC(ret, name, args, cargs) \ ++ret gnutls_zstd_func_##name args \ ++{ \ ++ ENSURE_LIBRARY; \ ++ assert (gnutls_zstd_sym_##name); \ ++ gnutls_zstd_sym_##name cargs; \ ++} ++#include "zstdfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++static int ++ensure_symbol (const char *name, void **symp) ++{ ++ if (!*symp) ++ { ++ void *sym = dlsym (gnutls_zstd_dlhandle, name); ++ if (!sym) ++ return -errno; ++ *symp = sym; ++ } ++ return 0; ++} ++ ++int ++gnutls_zstd_ensure_library (const char *soname, int flags) ++{ ++ int err; ++ ++ if (!gnutls_zstd_dlhandle) ++ { ++ gnutls_zstd_dlhandle = dlopen (soname, flags); ++ if (!gnutls_zstd_dlhandle) ++ return -errno; ++ } ++ ++#define ENSURE_SYMBOL(name) \ ++ ensure_symbol(#name, (void **)&gnutls_zstd_sym_##name) ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ err = ENSURE_SYMBOL(name); \ ++ if (err < 0) \ ++ return err; ++#define VOID_FUNC FUNC ++#include "zstdfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef ENSURE_SYMBOL ++ return 0; ++} ++ ++void ++gnutls_zstd_unload_library (void) ++{ ++ if (gnutls_zstd_dlhandle) ++ dlclose (gnutls_zstd_dlhandle); ++ ++#pragma GCC diagnostic push ++#pragma GCC diagnostic ignored "-Wunused-macros" ++ ++#define FUNC(ret, name, args, cargs) \ ++ gnutls_zstd_sym_##name = NULL; ++#define VOID_FUNC FUNC ++#include "zstdfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#pragma GCC diagnostic pop ++ ++#undef RESET_SYMBOL ++} ++ ++#else /* GNUTLS_ZSTD_ENABLE_DLOPEN */ ++ ++int ++gnutls_zstd_ensure_library (const char *soname, int flags) ++{ ++ (void) soname; ++ (void) flags; ++ return 0; ++} ++ ++void ++gnutls_zstd_unload_library (void) ++{ ++} ++ ++#endif /* !GNUTLS_ZSTD_ENABLE_DLOPEN */ +diff --git a/lib/dlwrap/zstd.h b/lib/dlwrap/zstd.h +new file mode 100644 +index 0000000000..80ac2fbd46 +--- /dev/null ++++ b/lib/dlwrap/zstd.h +@@ -0,0 +1,47 @@ ++/* ++ * Copying and distribution of this file, with or without modification, ++ * are permitted in any medium without royalty provided the copyright ++ * notice and this notice are preserved. This file is offered as-is, ++ * without any warranty. ++ */ ++ ++#ifndef GNUTLS_LIB_DLWRAP_ZSTD_H_ ++#define GNUTLS_LIB_DLWRAP_ZSTD_H_ ++ ++#include ++ ++#if defined(GNUTLS_ZSTD_ENABLE_DLOPEN) && GNUTLS_ZSTD_ENABLE_DLOPEN ++ ++#define FUNC(ret, name, args, cargs) \ ++ ret gnutls_zstd_func_##name args; ++#define VOID_FUNC FUNC ++#include "zstdfuncs.h" ++#undef VOID_FUNC ++#undef FUNC ++ ++#define GNUTLS_ZSTD_FUNC(name) gnutls_zstd_func_##name ++ ++#else ++ ++#define GNUTLS_ZSTD_FUNC(name) name ++ ++#endif /* GNUTLS_ZSTD_ENABLE_DLOPEN */ ++ ++/* Ensure SONAME to be loaded with dlopen FLAGS, and all the necessary ++ * symbols are resolved. ++ * ++ * Returns 0 on success; negative error code otherwise. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++int gnutls_zstd_ensure_library (const char *soname, int flags); ++ ++/* Unload library and reset symbols. ++ * ++ * Note that this function is NOT thread-safe; when calling it from ++ * multi-threaded programs, protect it with a locking mechanism. ++ */ ++void gnutls_zstd_unload_library (void); ++ ++#endif /* GNUTLS_LIB_DLWRAP_ZSTD_H_ */ +diff --git a/lib/dlwrap/zstdfuncs.h b/lib/dlwrap/zstdfuncs.h +new file mode 100644 +index 0000000000..8e3eb9ff59 +--- /dev/null ++++ b/lib/dlwrap/zstdfuncs.h +@@ -0,0 +1,15 @@ ++/* ++ * This file was automatically generated from zstd.h, ++ * which is covered by the following license: ++ * Copyright (c) Meta Platforms, Inc. and affiliates. ++ * All rights reserved. ++ * ++ * This source code is licensed under both the BSD-style license (found in the ++ * LICENSE file in the root directory of this source tree) and the GPLv2 (found ++ * in the COPYING file in the root directory of this source tree). ++ * You may select, at your option, one of the above-listed licenses. ++ */ ++FUNC(size_t, ZSTD_compress, (void *dst, size_t dstCapacity, const void *src, size_t srcSize, int compressionLevel), (dst, dstCapacity, src, srcSize, compressionLevel)) ++FUNC(size_t, ZSTD_decompress, (void *dst, size_t dstCapacity, const void *src, size_t compressedSize), (dst, dstCapacity, src, compressedSize)) ++FUNC(size_t, ZSTD_compressBound, (size_t srcSize), (srcSize)) ++FUNC(unsigned int, ZSTD_isError, (size_t code), (code)) +-- +2.45.2 + diff --git a/gnutls.spec b/gnutls.spec index 3bb7052..30a0423 100644 --- a/gnutls.spec +++ b/gnutls.spec @@ -18,6 +18,7 @@ Patch: gnutls-3.2.7-rpath.patch # follow https://gitlab.com/gnutls/gnutls/-/issues/1443 Patch: gnutls-3.7.8-ktls_skip_tls12_chachapoly_test.patch +Patch: gnutls-3.8.6-compression-dlwrap.patch %bcond_without bootstrap %bcond_without dane