]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
RAR5 reader: invalid window buffer read in E8E9 filter 1172/head
authorGrzegorz Antoniak <ga@anadoxin.org>
Sat, 2 Feb 2019 07:46:24 +0000 (08:46 +0100)
committerGrzegorz Antoniak <ga@anadoxin.org>
Wed, 17 Apr 2019 03:56:39 +0000 (05:56 +0200)
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.

libarchive/archive_read_support_format_rar5.c

index 159c3b61f5ff29b592c576aec93021408bd3a379..0058f1e168b8bfe725cadc2c2f9a60d67e8ac8b6 100644 (file)
@@ -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 =