From dc6c0c5f3567d7127ccbd8456a749af008e57ba5 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 31 Oct 2025 22:30:09 -0700 Subject: [PATCH] Fix a buffer overrun when reading truncated 7zip headers This adjusts the request size for reading data from a 7zip SFX header to ensure we get enough bytes to cover the following checks. Resolves #2765 --- Makefile.am | 2 + libarchive/archive_read_support_format_7zip.c | 8 ++- libarchive/test/CMakeLists.txt | 1 + .../test_read_format_7zip_issue2765.7z.uu | 5 ++ .../test/test_read_format_7zip_issue2765.c | 55 +++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 libarchive/test/test_read_format_7zip_issue2765.7z.uu create mode 100644 libarchive/test/test_read_format_7zip_issue2765.c diff --git a/Makefile.am b/Makefile.am index 2827615ad..25b365b94 100644 --- a/Makefile.am +++ b/Makefile.am @@ -466,6 +466,7 @@ libarchive_test_SOURCES= \ libarchive/test/test_read_format_7zip_encryption_data.c \ libarchive/test/test_read_format_7zip_encryption_partially.c \ libarchive/test/test_read_format_7zip_encryption_header.c \ + libarchive/test/test_read_format_7zip_issue2765.c \ libarchive/test/test_read_format_7zip_malformed.c \ libarchive/test/test_read_format_7zip_packinfo_digests.c \ libarchive/test/test_read_format_ar.c \ @@ -813,6 +814,7 @@ libarchive_test_EXTRA_DIST=\ libarchive/test/test_read_format_7zip_encryption_header.7z.uu \ libarchive/test/test_read_format_7zip_encryption_partially.7z.uu \ libarchive/test/test_read_format_7zip_extract_second.7z.uu \ + libarchive/test/test_read_format_7zip_issue2765.7z.uu \ libarchive/test/test_read_format_7zip_lzma1.7z.uu \ libarchive/test/test_read_format_7zip_lzma1_2.7z.uu \ libarchive/test/test_read_format_7zip_lzma1_lzma2.7z.uu \ diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c index 595462733..330d5515d 100644 --- a/libarchive/archive_read_support_format_7zip.c +++ b/libarchive/archive_read_support_format_7zip.c @@ -744,6 +744,7 @@ find_elf_data_sec(struct archive_read *a) const char *h; char big_endian, format_64; ssize_t bytes, min_addr = SFX_MIN_ADDR; + ssize_t request; uint64_t e_shoff, strtab_offset, strtab_size; uint16_t e_shentsize, e_shnum, e_shstrndx; uint16_t (*dec16)(const void *); @@ -796,7 +797,12 @@ find_elf_data_sec(struct archive_read *a) if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) { break; } - h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL); + if (format_64) { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x28; + } else { + request = (size_t)e_shnum * (size_t)e_shentsize + 0x18; + } + h = __archive_read_ahead(a, request, &bytes); if (h == NULL) { break; } diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index f62737d79..02521c2bc 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -108,6 +108,7 @@ IF(ENABLE_TEST) test_read_format_7zip_encryption_data.c test_read_format_7zip_encryption_header.c test_read_format_7zip_encryption_partially.c + test_read_format_7zip_issue2765.c test_read_format_7zip_malformed.c test_read_format_7zip_packinfo_digests.c test_read_format_ar.c diff --git a/libarchive/test/test_read_format_7zip_issue2765.7z.uu b/libarchive/test/test_read_format_7zip_issue2765.7z.uu new file mode 100644 index 000000000..734561a20 --- /dev/null +++ b/libarchive/test/test_read_format_7zip_issue2765.7z.uu @@ -0,0 +1,5 @@ +begin 644 test_read_format_7zip_issue2765.7z +M?T5,1@$!`0!@```(0``````````R````-``@``$````````````````````` +D1TD``0`!````4$L`