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:
1 parent
2c40fc5563
commit
833f14d563
2 files changed
+38
-19
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user