From: Grzegorz Antoniak Date: Sat, 2 Feb 2019 07:46:24 +0000 (+0100) Subject: RAR5 reader: invalid window buffer read in E8E9 filter X-Git-Tag: v3.4.0~55^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F1172%2Fhead;p=thirdparty%2Flibarchive.git RAR5 reader: invalid window buffer read in E8E9 filter The E8E9 filter was accessing the window buffer with a direct memory read. But since the window buffer is a circular buffer, some of its data can span between the end of the buffer and beginning of the buffer. This means that accessing the window buffer needs to be done always by a reading function that is aware of the fact that the window buffer is circular. The commit changes direct memory read to the access through the circular_memcpy() function. This fixes some edge cases when the E8E9 filter data (4 bytes) is spanned between the end of the window buffer and the beginning of the buffer. This situation can happen in archives compressed with a small dictionary size. --- diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c index 159c3b61f..0058f1e16 100644 --- a/libarchive/archive_read_support_format_rar5.c +++ b/libarchive/archive_read_support_format_rar5.c @@ -450,16 +450,6 @@ static inline struct rar5* get_context(struct archive_read* a) { /* Convenience functions used by filter implementations. */ -static uint32_t read_filter_data(struct rar5* rar, uint32_t offset) { - return archive_le32dec(&rar->cstate.window_buf[offset]); -} - -static void write_filter_data(struct rar5* rar, uint32_t offset, - uint32_t value) -{ - archive_le32enc(&rar->cstate.filtered_buf[offset], value); -} - static void circular_memcpy(uint8_t* dst, uint8_t* window, const int mask, int64_t start, int64_t end) { @@ -474,6 +464,19 @@ static void circular_memcpy(uint8_t* dst, uint8_t* window, const int mask, } } +static uint32_t read_filter_data(struct rar5* rar, uint32_t offset) { + uint8_t linear_buf[4]; + circular_memcpy(linear_buf, rar->cstate.window_buf, rar->cstate.window_mask, + offset, offset + 4); + return archive_le32dec(linear_buf); +} + +static void write_filter_data(struct rar5* rar, uint32_t offset, + uint32_t value) +{ + archive_le32enc(&rar->cstate.filtered_buf[offset], value); +} + /* Allocates a new filter descriptor and adds it to the filter array. */ static struct filter_info* add_new_filter(struct rar5* rar) { struct filter_info* f =