]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
RAR5 reader: fix integer overflow 1187/head
authorGrzegorz Antoniak <ga@anadoxin.org>
Sat, 4 May 2019 04:54:07 +0000 (06:54 +0200)
committerGrzegorz Antoniak <ga@anadoxin.org>
Sat, 4 May 2019 04:54:07 +0000 (06:54 +0200)
This commit fixes an integer overflow triggering on invalid files during
decompression.

Also added a unit test.

Should fix OSSFuzz issue #14555.

libarchive/archive_read_support_format_rar5.c
libarchive/test/test_read_format_rar5.c
libarchive/test/test_read_format_rar5_distance_overflow.rar.uu [new file with mode: 0644]

index a2e5b68e73b4739c3262b12feaff330df661aa00..370c663d52f245f997350ff2dd2eefc8ea93589f 100644 (file)
@@ -2811,6 +2811,14 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                         return ARCHIVE_FATAL;
                     }
 
+                    if(dist >= INT_MAX - low_dist - 1) {
+                        /* This only happens in invalid archives. */
+                        archive_set_error(&a->archive,
+                            ARCHIVE_ERRNO_FILE_FORMAT,
+                            "Distance pointer overflow");
+                        return ARCHIVE_FATAL;
+                    }
+
                     dist += low_dist;
                 } else {
                     /* dbits is one of [0,1,2,3] */
index 5248172b0ecb09788e134fe6d1a7fa2a7c7b450c..a0f278133c85a9caafcd0de837f1211890fa05fa 100644 (file)
@@ -1036,4 +1036,19 @@ DEFINE_TEST(test_read_format_rar5_invalid_dict_reference)
     assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
 
     EPILOGUE();
-}
\ No newline at end of file
+}
+
+DEFINE_TEST(test_read_format_rar5_distance_overflow)
+{
+    uint8_t buf[16];
+
+    PROLOGUE("test_read_format_rar5_distance_overflow.rar");
+
+    assertA(0 == archive_read_next_header(a, &ae));
+    /* This archive is invalid. However, processing it shouldn't cause any
+     * errors related to variable overflows when using -fsanitize. */
+    assertA(ARCHIVE_FATAL == archive_read_data(a, buf, sizeof(buf)));
+    assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
+
+    EPILOGUE();
+}
diff --git a/libarchive/test/test_read_format_rar5_distance_overflow.rar.uu b/libarchive/test/test_read_format_rar5_distance_overflow.rar.uu
new file mode 100644 (file)
index 0000000..8fefa28
--- /dev/null
@@ -0,0 +1,9 @@
+begin 644 test_read_format_rar5_distance_overflow.rar
+M4F%R(1H'`0"-[P+2``(''/\@("`@_R4``B`@("`@("`@("`@(/__("`@("`@
+M(/\@("`@("`@((9ML63,PX"&AK%:S+?_(/\@_R#_(/\@_R#_(/\@`"``!R`@
+MR<G)``#_(,G)R?___R#___\@____(/___R#___\@____R4#)R<G___\@____
+M(/\@____("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(/__________
+M____________________________________________________("`@("`@
+.("`@("`@("`@("#_("``
+`
+end