]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
RAR5 reader: use unsigned int for volume number and check for range
authorMartin Matuska <martin@matuska.org>
Sat, 20 Apr 2019 10:12:28 +0000 (12:12 +0200)
committerMartin Matuska <martin@matuska.org>
Sat, 20 Apr 2019 12:10:51 +0000 (14:10 +0200)
Fix an possible integer overflow.

Reported by: OSS-Fuzz issue 13965

libarchive/archive_read_support_format_rar5.c

index a43afbfa0fc67a2a373e1fa52f3800b69f35f2b7..cab50f8303b656a2f4b5d2662e3449283a2f0fb0 100644 (file)
@@ -33,6 +33,9 @@
 #ifdef HAVE_ZLIB_H
 #include <zlib.h> /* crc32 */
 #endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
 
 #include "archive.h"
 #ifndef HAVE_ZLIB_H
@@ -281,7 +284,7 @@ struct main_header {
     uint8_t endarc : 1;
     uint8_t notused : 5;
 
-    int vol_no;
+    unsigned int vol_no;
 };
 
 struct generic_header {
@@ -293,7 +296,7 @@ struct generic_header {
 };
 
 struct multivolume {
-    int expected_vol_no;
+    unsigned int expected_vol_no;
     uint8_t* push_buf;
 };
 
@@ -1722,8 +1725,12 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
         if(!read_var_sized(a, &v, NULL)) {
             return ARCHIVE_EOF;
         }
-
-        rar->main.vol_no = (int) v;
+       if (v > UINT_MAX) {
+           archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+               "Invalid volume number");
+           return ARCHIVE_FATAL;
+       }
+        rar->main.vol_no = (unsigned int) v;
     } else {
         rar->main.vol_no = 0;
     }
@@ -1941,6 +1948,11 @@ static int process_base_block(struct archive_read* a,
                 if(ret == ARCHIVE_FATAL) {
                     return ARCHIVE_EOF;
                 } else {
+                   if(rar->vol.expected_vol_no == UINT_MAX) {
+                       archive_set_error(&a->archive,
+                           ARCHIVE_ERRNO_FILE_FORMAT, "Header error");
+                       return ARCHIVE_FATAL;
+                   }
                     rar->vol.expected_vol_no = rar->main.vol_no + 1;
                     return ARCHIVE_OK;
                 }