Commit d36af7dfc for clamav.net

commit d36af7dfcd316385d0001ba6ab99aa0ea5927ede
Author: Valerie Snyder <valsnyde@cisco.com>
Date:   Mon Apr 27 15:42:22 2026 -0400

    HFS+: avoid inflateEnd on uninitialized HFS+ cmpf streams

    A crafted HFS+ cmpf resource block can take the uncompressed
    path without initializing a zlib stream, but the block
    cleanup still calls inflateEnd(). On our repro attempts this
    produced a parser-local Z_STREAM_ERROR rather than a process
    crash.

    Initialize the z_stream defensively, track whether
    inflateInit2() succeeded, and only call inflateEnd() for
    initialized streams.

    Credit: Mizu

    CLAM-2976

diff --git a/libclamav/hfsplus.c b/libclamav/hfsplus.c
index 57f147310..4a2bd7209 100644
--- a/libclamav/hfsplus.c
+++ b/libclamav/hfsplus.c
@@ -1277,9 +1277,10 @@ static cl_error_t hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHea
                                             off_t blockOffset = dataOffset + table[curBlock].offset;
                                             size_t curOffset;
                                             size_t readLen;
-                                            z_stream stream;
+                                            z_stream stream = {0};
                                             int streamBeginning  = 1;
                                             int streamCompressed = 0;
+                                            int streamInitialized = 0;

                                             cli_dbgmsg("Handling block %u of %" PRIu32 " at offset %" PRIi64 " (size %u)\n", curBlock, numBlocks, (int64_t)blockOffset, table[curBlock].length);

@@ -1319,6 +1320,7 @@ static cl_error_t hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHea
                                                             status = CL_EFORMAT;
                                                             goto done;
                                                         }
+                                                        streamInitialized = 1;
                                                     }
                                                 }

@@ -1367,10 +1369,12 @@ static cl_error_t hfsplus_walk_catalog(cli_ctx *ctx, hfsPlusVolumeHeader *volHea
                                                 streamBeginning = 0;
                                             }

-                                            if (Z_OK != (z_ret = inflateEnd(&stream))) {
-                                                cli_dbgmsg("hfsplus_walk_catalog: inflateEnd failed (%d)\n", z_ret);
-                                                status = CL_EFORMAT;
-                                                goto done;
+                                            if (streamInitialized) {
+                                                if (Z_OK != (z_ret = inflateEnd(&stream))) {
+                                                    cli_dbgmsg("hfsplus_walk_catalog: inflateEnd failed (%d)\n", z_ret);
+                                                    status = CL_EFORMAT;
+                                                    goto done;
+                                                }
                                             }
                                         }