Commit 045ca33cef for openssl.org

commit 045ca33cef8d1585ecb9ee8a4ef04e6e790f6828
Author: SiteRelEnby <125829806+SiteRelEnby@users.noreply.github.com>
Date:   Wed Jan 21 02:57:52 2026 +0000

    Fix NULL pointer dereference when zlib DSO fails to load

    When ZLIB_SHARED is defined and DSO_load() fails to load the zlib
    library, ossl_comp_zlib_init() incorrectly returns 1 (success) while
    leaving all function pointers (p_compress, p_uncompress, etc.) as NULL.

    This causes COMP_zlib() and COMP_zlib_oneshot() to return valid-looking
    COMP_METHOD pointers, but when these methods are used (e.g., during
    TLS 1.3 certificate decompression), the NULL function pointers are
    dereferenced, causing a SIGSEGV crash.

    The bug occurs because the NULL pointer check (lines 297-303) was inside
    the `if (zlib_dso != NULL)` block, so it was skipped entirely when
    DSO_load() returned NULL.

    The fix moves the NULL pointer check outside the conditional block,
    consistent with how c_brotli.c and c_zstd.c handle this case. Now if
    the DSO fails to load, all function pointers remain NULL, the check
    catches this, and the function correctly returns 0 (failure).

    This also fixes an incorrect cast of p_uncompress from compress_ft to
    the correct uncompress_ft type.

    PoC demonstrating the bug: https://github.com/SiteRelEnby/openssl-zlib-poc

    Fixes #23563

    CLA: trivial

    Reviewed-by: Paul Yang <paulyang.inf@gmail.com>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    MergeDate: Thu Jan 22 17:00:50 2026
    (Merged from https://github.com/openssl/openssl/pull/29699)

diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c
index 602259c821..2fdacc3593 100644
--- a/crypto/comp/c_zlib.c
+++ b/crypto/comp/c_zlib.c
@@ -284,7 +284,7 @@ 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_uncompress = (uncompress_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_");
@@ -292,14 +292,14 @@ DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init)
         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_uncompress == 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;
-        }
+    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) {
+        ossl_comp_zlib_cleanup();
+        return 0;
     }
 #endif
     return 1;