]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
7zip: Fix more 32 bit truncations 3006/head
authorTobias Stoeckmann <tobias@stoeckmann.org>
Mon, 27 Apr 2026 16:08:46 +0000 (18:08 +0200)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 6 May 2026 18:11:18 +0000 (20:11 +0200)
Check for truncations before casting uint64_t to size_t for 32 bit
system safety.

Reported by Asaf Meizner.
Resolves additional notes in GHSA-rf5v-vf7c-6wvg.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
libarchive/archive_read_support_format_7zip.c

index 058b29a50c15cd99057fe1eba1d0440f37564316..0da406d59a40f577063303a8c8b310769b040847 100644 (file)
@@ -1037,6 +1037,13 @@ archive_read_format_7zip_read_header(struct archive_read *a,
                unsigned char *symname = NULL;
                size_t symsize = 0;
 
+               if (zip->entry_bytes_remaining > 1024 * 1024) {
+                       archive_set_error(&a->archive, ENOMEM,
+                           "Rejecting malformed 7zip archive: "
+                           "symlink contents exceed 1 megabyte");
+                       return (ARCHIVE_FATAL);
+               }
+
                /*
                 * Symbolic-name is recorded as its contents. We have to
                 * read the contents at this time.
@@ -2836,7 +2843,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
 
                if (parse_7zip_uint64(a, &size) < 0)
                        return (-1);
-               if (zip->header_bytes_remaining < size)
+               if (zip->header_bytes_remaining < size || size > SIZE_MAX / 4)
                        return (-1);
                ll = (size_t)size;
 
@@ -3839,6 +3846,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
                ssize_t bytes;
                unsigned char *b[3] = {NULL, NULL, NULL};
                uint64_t sunpack[3] ={-1, -1, -1};
+               uint64_t remaining;
                size_t s[3] = {0, 0, 0};
                int idx[3] = {0, 1, 2};
 
@@ -3893,12 +3901,14 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
                        coder2 = &(fc[3]);
                        zip->main_stream_bytes_remaining =
                                (size_t)folder->unPackSize[2];
+                       remaining = folder->unPackSize[2];
                } else if (coder2 != NULL && coder2->codec == _7Z_X86_BCJ2 &&
                    zip->pack_stream_remaining == 4 &&
                    folder->numInStreams == 5 && folder->numOutStreams == 2) {
                        /* Source type 0 made by 7z */
                        zip->main_stream_bytes_remaining =
                                (size_t)folder->unPackSize[0];
+                       remaining = folder->unPackSize[0];
                } else {
                        /* We got an unexpected form. */
                        archive_set_error(&(a->archive),
@@ -3906,6 +3916,15 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
                            "Unsupported form of BCJ2 streams");
                        return (ARCHIVE_FATAL);
                }
+               if (remaining > SIZE_MAX) {
+                       archive_set_error(&(a->archive),
+                           ARCHIVE_ERRNO_MISC,
+                           "7-Zip sub-stream size exceeds "
+                           "platform maximum");
+                       return (ARCHIVE_FATAL);
+               }
+               zip->main_stream_bytes_remaining = remaining;
+
 
                /* Skip the main stream at this time. */
                if ((r = seek_pack(a)) < 0)