Commit 01745181c for clamav.net
commit 01745181c7f6c712d015abc78fe4b756e094bc39
Author: Val S. <valsnyde@cisco.com>
Date: Fri Aug 7 13:46:28 2026 -0400
Libclamav: fix ZIP catalogue invalid free (#68)
The ZIP local-header indexing path merges records from the central
directory with records found by scanning local file headers. The merge used
shallow struct copies, so the combined catalogue and source catalogues could
share the same original_filename pointer.
If overlap detection failed after the merge copied entries, cleanup could
free the source catalogue names and then free the same pointers again from
the combined catalogue.
Add a small zip_record_move() helper and use it for the merge so ownership
of original_filename transfers to the combined catalogue before any later
cleanup.
CLAM-3003
diff --git a/libclamav/unzip.c b/libclamav/unzip.c
index 07d118824..3c6938ffa 100644
--- a/libclamav/unzip.c
+++ b/libclamav/unzip.c
@@ -85,6 +85,15 @@ struct zip_record {
char *original_filename;
};
+/**
+ * @brief Move a zip record and its owned resources to another record.
+ */
+static void zip_record_move(struct zip_record *dst, struct zip_record *src)
+{
+ *dst = *src;
+ src->original_filename = NULL;
+}
+
static int wrap_inflateinit2(void *a, int b)
{
return inflateInit2(a, b);
@@ -1561,11 +1570,15 @@ cl_error_t index_local_file_headers(
(temp_catalogue_offset < local_file_headers_count &&
temp_catalogue[temp_catalogue_offset].local_header_offset < (*catalogue)[catalogue_offset].local_header_offset)) {
// add entry from temp_catalogue into the list
- combined_catalogue[i] = temp_catalogue[temp_catalogue_offset];
+ zip_record_move(
+ &combined_catalogue[i],
+ &temp_catalogue[temp_catalogue_offset]);
temp_catalogue_offset++;
} else {
// add entry from the catalogue into the list
- combined_catalogue[i] = (*catalogue)[catalogue_offset];
+ zip_record_move(
+ &combined_catalogue[i],
+ &((*catalogue)[catalogue_offset]));
catalogue_offset++;
}