]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
[7zip] Sanity-check the number of files 2980/head
authorTim Kientzle <kientzle@acm.org>
Sat, 25 Apr 2026 18:58:17 +0000 (14:58 -0400)
committerTim Kientzle <kientzle@acm.org>
Sat, 25 Apr 2026 18:58:17 +0000 (14:58 -0400)
We allocate space early on to support the advertised number of
files. A malicious archive can set a nonsensical value here to exhaust
memory. This adds a check comparing the number of files to the number
of streams and the size of the total header.

Note that the just-added test does not actually fail without this.
The existing code recovers if the allocation fails, which it typically
will.  The new check tightens the limit so that we reject nonsensical
file counts and avoid problems from large memory allocations.

libarchive/archive_read_support_format_7zip.c

index 8926ac50a1ed3843f051ef1f57dd9a180fec30c1..679599b85fa75d6e3bfa7c21d100c13606b3d9eb 100644 (file)
@@ -2808,6 +2808,14 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
                return (-1);
        if (UMAX_ENTRY < zip->numFiles)
                return (-1);
+       /* Empty-file entries (those beyond the known stream count) require a
+        * kEmptyStream bitmap of ceil(numFiles/8) bytes; reject if that cannot
+        * fit in the remaining header bytes. Non-empty files need no header
+        * space here because they map directly to already-parsed streams. */
+       if (zip->numFiles > (uint64_t)zip->si.ss.unpack_streams &&
+           zip->numFiles - (uint64_t)zip->si.ss.unpack_streams >
+           8 * zip->header_bytes_remaining)
+               return (-1);
 
        zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries));
        if (zip->entries == NULL)