Skip to content

RAR5 reader: reject files that declare invalid header flags #1326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
RAR5 reader: reject files that declare invalid header flags
One of the fields in RAR5's base block structure is the size of the
header. Some invalid files declare a 0 header size setting, which can
confuse the unpacker. Minimum header size for RAR5 base blocks is 7
bytes (4 bytes for CRC, and 3 bytes for the rest), so block size of 0
bytes should be rejected at header parsing stage.

The fix adds an error condition if header size of 0 bytes is detected.
In this case, the unpacker will not attempt to unpack the file, as the
header is corrupted.

The commit also adds OSSFuzz #20459 sample to test further regressions
in this area.
  • Loading branch information
antekone committed Feb 2, 2020
commit 94821008d6eea81e315c5881cdf739202961040a
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_rar5_win32.rar.uu \
libarchive/test/test_read_format_rar5_arm_filter_on_window_boundary.rar.uu \
libarchive/test/test_read_format_rar5_different_winsize_on_merge.rar.uu \
libarchive/test/test_read_format_rar5_block_size_is_too_small.rar.uu \
libarchive/test/test_read_format_raw.bufr.uu \
libarchive/test/test_read_format_raw.data.gz.uu \
libarchive/test/test_read_format_raw.data.Z.uu \
Expand Down
17 changes: 15 additions & 2 deletions libarchive/archive_read_support_format_rar5.c
Original file line number Diff line number Diff line change
Expand Up @@ -2085,6 +2085,8 @@ static int scan_for_signature(struct archive_read* a);
static int process_base_block(struct archive_read* a,
struct archive_entry* entry)
{
const size_t SMALLEST_RAR5_BLOCK_SIZE = 3;

struct rar5* rar = get_context(a);
uint32_t hdr_crc, computed_crc;
size_t raw_hdr_size = 0, hdr_size_len, hdr_size;
Expand Down Expand Up @@ -2114,15 +2116,26 @@ static int process_base_block(struct archive_read* a,
return ARCHIVE_EOF;
}

hdr_size = raw_hdr_size + hdr_size_len;

/* Sanity check, maximum header size for RAR5 is 2MB. */
if(raw_hdr_size > (2 * 1024 * 1024)) {
if(hdr_size > (2 * 1024 * 1024)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Base block header is too large");

return ARCHIVE_FATAL;
}

hdr_size = raw_hdr_size + hdr_size_len;
/* Additional sanity checks to weed out invalid files. */
if(raw_hdr_size == 0 || hdr_size_len == 0 ||
hdr_size < SMALLEST_RAR5_BLOCK_SIZE)
{
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Too small block encountered (%ld bytes)",
raw_hdr_size);

return ARCHIVE_FATAL;
}

/* Read the whole header data into memory, maximum memory use here is
* 2MB. */
Expand Down
15 changes: 15 additions & 0 deletions libarchive/test/test_read_format_rar5.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,3 +1256,18 @@ DEFINE_TEST(test_read_format_rar5_different_winsize_on_merge)

EPILOGUE();
}

DEFINE_TEST(test_read_format_rar5_block_size_is_too_small)
{
char buf[4096];
PROLOGUE("test_read_format_rar5_block_size_is_too_small.rar");

/* This file is damaged, so those functions should return failure.
* Additionally, SIGSEGV shouldn't be raised during execution
* of those functions. */

assertA(archive_read_next_header(a, &ae) != ARCHIVE_OK);
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);

EPILOGUE();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
begin 644 test_read_format_rar5_block_size_is_too_small.rar
M4F%R(1H'`0"-[P+2``+'(!P,("`@N`,!`B`@("`@("`@("`@("`@("#_("`@
M("`@("`@("`@((:Q;2!4-'-^4B`!((WO`M(``O\@$/\@-R`@("`@("`@("`@
M``X@("`@("`@____("`@("`@(/\@("`@("`@("`@("#_(+6U,2"UM;6UM[CU
M)B`@*(0G(`!.`#D\3R``(/__(,+_````-0#_($&%*/HE=C+N`"```"```"`D
J`)$#("#_("#__P`@__\@_R#_("`@("`@("#_("#__R`@(/__("#__R`"
`
end