Merge pull request #3015 from datauwu/master

rar: avoid reading NEWSUB extended data during header parsing
(cherry picked from commit 6246a35326)
This commit is contained in:
Tim Kientzle authored and Martin Matuska committed 2026-06-23 10:27:52 +02:00
1 parent 2c40fc5563
commit 833f14d563
2 files changed
+38 -19

No files matched your search

+9 -19
View File
@@ -124,6 +124,7 @@
#define NS_UNIT 10000000
#define DICTIONARY_MAX_SIZE 0x400000
#define RAR_MAX_NEWSUB_SIZE (1024 * 1024)
#define MAINCODE_SIZE 299
#define OFFSETCODE_SIZE 60
@@ -1513,27 +1514,20 @@ read_header(struct archive_read *a, struct archive_entry *entry,
* consumed at the end.
*/
if (head_type == NEWSUB_HEAD) {
size_t distance = p - (const char *)h;
if (rar->packed_size > INT64_MAX - header_size) {
if (rar->packed_size > RAR_MAX_NEWSUB_SIZE ||
rar->packed_size > INT64_MAX - header_size) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Extended header size too large");
"Invalid RAR file: Overlarge extended header");
return (ARCHIVE_FATAL);
}
header_size += rar->packed_size;
if ((uintmax_t)header_size > SIZE_MAX) {
if (__archive_read_consume(a, header_size + rar->packed_size - 7) < 0) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Unable to read extended header data");
"Invalid RAR file: Cannot read extended header data");
return (ARCHIVE_FATAL);
}
/* Make sure we have the extended data. */
if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Failed to read extended header data");
return (ARCHIVE_FATAL);
}
p = h;
endp = p + header_size - 7;
p += distance;
/* NEWSUB blocks are metadata-only here; skip them without creating an entry. */
return ret;
}
filename_size = archive_le16dec(file_header.name_size);
@@ -1829,10 +1823,6 @@ read_header(struct archive_read *a, struct archive_entry *entry,
rar->ppmd_valid = rar->ppmd_eod = 0;
rar->filters.filterstart = INT64_MAX;
/* Don't set any archive entries for non-file header types */
if (head_type == NEWSUB_HEAD)
return ret;
archive_entry_set_mtime(entry, rar->mtime, rar->mnsec);
archive_entry_set_ctime(entry, rar->ctime, rar->cnsec);
archive_entry_set_atime(entry, rar->atime, rar->ansec);
+29
View File
@@ -3906,6 +3906,35 @@ DEFINE_TEST(test_read_format_rar_newsub_huge)
#endif
}
DEFINE_TEST(test_read_format_rar_newsub_huge64)
{
static const unsigned char archive[] = {
'R', 'a', 'r', '!', 0x1a, 0x07, 0x00,
0x23, 0x25, 0x7a, 0x00, 0x01, 0x28, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0x7f, 0x00, 0x00, 0x00, 0x00
};
struct archive_entry *ae;
struct archive *a;
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_memory(a, archive, sizeof(archive)));
failure("Malformed RAR NEWSUB header should be rejected before "
"extended data read-ahead");
assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
assertEqualString("Invalid RAR file: Overlarge extended header",
archive_error_string(a));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_read_format_rar_symlink_huge)
{
#if SIZE_MAX == UINT64_MAX