Segmentation fault while reading a RAR file
eriklax opened this issue · comments
On Linux and FreeBSD, while reading a specific "RAR archive data, v4, os: Win32" file, and while not reading all data in all files (hence skipping over with archive_read_data_skip). When reaching a specific file in a archive this crash occurres.
Important! If not skipping file < 141, and reading all data, it does not crash
Backtrace:
Program received signal SIGSEGV, Segmentation fault.
Address not mapped to object.
0x00000008004b621f in memcpy () from /lib/libc.so.7
(gdb) bt
#0 0x00000008004b621f in memcpy () from /lib/libc.so.7
#1 0x00000008002db819 in copy_from_lzss_window_to_unp (a=0x80121a000, buffer=0x7fffffffe988, startpos=1280, length=-855)
at /build/libarchive/libarchive/archive_read_support_format_rar.c:3102
#2 0x00000008002db642 in read_data_compressed (a=0x80121a000, buff=0x7fffffffe988, size=0x7fffffffe980, offset=0x7fffffffe978, looper=1)
at /build/libarchive/libarchive/archive_read_support_format_rar.c:2204
#3 0x00000008002d8417 in archive_read_format_rar_read_data (a=0x80121a000, buff=0x7fffffffe988, size=0x7fffffffe980, offset=0x7fffffffe978)
at /build/libarchive/libarchive/archive_read_support_format_rar.c:1130
#4 0x00000008002a1a82 in _archive_read_data_block (_a=0x80121a000, buff=0x7fffffffe988, size=0x7fffffffe980, offset=0x7fffffffe978)
at /build/libarchive/libarchive/archive_read.c:986
#5 0x00000008003090f6 in archive_read_data_block (a=0x80121a000, buff=0x7fffffffe988, s=0x7fffffffe980, o=0x7fffffffe978) at /build/libarchive/libarchive/archive_virtual.c:161
#6 0x0000000000201c83 in main ()
libarchive/libarchive/archive_read_support_format_rar.c
Lines 2183 to 2185 in 9ba8292
This expand() make the end go from
start = 1280 end = 1792
to
start = 1280 end = 425
Explaining the length=-855 from the gdb backtrace
#include <archive.h>
#include <archive_entry.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
struct archive* archive = archive_read_new();
archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);
if (archive_read_open_filename(archive, argv[1], 10240) != ARCHIVE_OK)
return 1;
struct archive_entry *entry;
const void *buff = NULL;
size_t size = 0;
off_t offset = 0;
int r;
size_t y = 0;
while (++y)
{
int r = archive_read_next_header(archive, &entry);
if (r != ARCHIVE_OK)
{
if (r == ARCHIVE_EOF)
break;
return 1;
}
if (archive_read_data_block(archive, &buff, &size, &offset) != ARCHIVE_OK)
break;
if (y < 141)
continue;
while ((r = archive_read_data_block(archive, &buff, &size, &offset)) == ARCHIVE_OK) // crashes here
;
}
archive_read_free(archive);
return 0;
}
I just ran into this issue last week as well. Making the change below to right after the expand()/if code seemed to fix crash:
- rar->bytes_uncopied = end - start;
+ rar->bytes_uncopied = end > start ? end - start : 0;
but I don't know if that has any unintended side effect. Would be good to get an "official" fix.