Merge pull request #3047 from legnaleurc/fix/rar-recovery-record

rar: skip NEWSUB payloads without size cap
(cherry picked from commit 82404ac239)
This commit is contained in:
Dustin L. Howett authored and Martin Matuska committed 2026-06-23 11:02:20 +02:00
1 parent b9cf20973f
commit 7cbf4a8817
4 files changed
+23336 -7

No files matched your search

+1
View File
@@ -976,6 +976,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_rar_multivolume.part0003.rar.uu \
libarchive/test/test_read_format_rar_multivolume.part0004.rar.uu \
libarchive/test/test_read_format_rar_newsub_huge.rar.uu \
libarchive/test/test_read_format_rar_newsub_rr_over_1m.rar.uu \
libarchive/test/test_read_format_rar_noeof.rar.uu \
libarchive/test/test_read_format_rar_overflow.rar.uu \
libarchive/test/test_read_format_rar_ppmd_lzss_conversion.rar.uu \
+6 -4
View File
@@ -124,7 +124,6 @@
#define NS_UNIT 10000000
#define DICTIONARY_MAX_SIZE 0x400000
#define RAR_MAX_NEWSUB_SIZE (1024 * 1024)
#define MAINCODE_SIZE 299
#define OFFSETCODE_SIZE 60
@@ -1514,8 +1513,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
* consumed at the end.
*/
if (head_type == NEWSUB_HEAD) {
if (rar->packed_size > RAR_MAX_NEWSUB_SIZE ||
rar->packed_size > INT64_MAX - header_size) {
if (rar->packed_size > INT64_MAX - header_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Invalid RAR file: Overlarge extended header");
return (ARCHIVE_FATAL);
@@ -1526,7 +1524,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
return (ARCHIVE_FATAL);
}
/* NEWSUB blocks are metadata-only here; skip them without creating an entry. */
/*
* NEWSUB records are metadata-only in this reader. The block header
* has already been validated, so it is safe to skip exactly the
* remaining header bytes and the associated data payload.
*/
return ret;
}
+22 -3
View File
@@ -3906,6 +3906,25 @@ DEFINE_TEST(test_read_format_rar_newsub_huge)
#endif
}
DEFINE_TEST(test_read_format_rar_newsub_rr_over_1m)
{
const char* reffile = "test_read_format_rar_newsub_rr_over_1m.rar";
struct archive_entry *ae;
struct archive *a;
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
assertA(0 == archive_read_support_format_rar(a));
assertA(0 == archive_read_open_filename(a, reffile, 10240));
failure("RAR NEWSUB RR records larger than 1 MiB should be skipped");
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_newsub_huge64)
{
static const unsigned char archive[] = {
@@ -3925,10 +3944,10 @@ DEFINE_TEST(test_read_format_rar_newsub_huge64)
assertA(0 == archive_read_support_format_rar(a));
assertA(0 == archive_read_open_memory(a, archive, sizeof(archive)));
failure("Malformed RAR NEWSUB header should be rejected before "
"extended data read-ahead");
failure("Malformed RAR NEWSUB header should be rejected if its "
"extended data is missing");
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualString("Invalid RAR file: Overlarge extended header",
assertEqualString("Invalid RAR file: Cannot read extended header data",
archive_error_string(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
File diff suppressed because it is too large. Load diff