Merge pull request #2769 from kientzle/kientzle-issue2765

Fix a buffer overrun when reading truncated 7zip headers
This commit is contained in:
Tim Kientzle 2025-11-02 14:17:48 -08:00 committed by GitHub
commit fa5f70627c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 66 additions and 1 deletions

View File

@ -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 \

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1,5 @@
begin 644 test_read_format_7zip_issue2765.7z
M?T5,1@$!`0!@```(0``````````R````-``@``$`````````````````````
D1TD``0`!````4$L`</]_```````````(````N`$```#-@```
`
end

View File

@ -0,0 +1,51 @@
/*-
* Copyright (c) 2025 Tim Kientzle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.h"
/*
* Sample file from Github Issue #2765
*/
DEFINE_TEST(test_read_format_7zip_issue2765)
{
const char *refname = "test_read_format_7zip_issue2765.7z";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(refname);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_FATAL,
archive_read_open_filename(a, refname, 10240));
/* End of archive. */
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualInt(0, archive_file_count(a));
/* Close the archive. */
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}