#define NS_UNIT 10000000
#define DICTIONARY_MAX_SIZE 0x400000
+#define RAR_MAX_NEWSUB_SIZE (1024 * 1024)
#define MAINCODE_SIZE 299
#define OFFSETCODE_SIZE 60
* 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);
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);
#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