File CVE-2015-8916.patch of Package libarchive.3431
commit 39eddd77dfb45677053824d2679c9bc42a0918f1
Author: dosomder <dosomder@users.noreply.github.com>
Date: Sat Mar 19 19:18:56 2016 +0100
Check flags for multivolume entries
Index: libarchive-3.1.2/libarchive/archive_read_support_format_rar.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_rar.c
+++ libarchive-3.1.2/libarchive/archive_read_support_format_rar.c
@@ -78,17 +78,17 @@
#define HD_ADD_SIZE_PRESENT 0x8000
/* File Header Flags */
-#define FHD_SPLIT_BEFORE 0x0001
-#define FHD_SPLIT_AFTER 0x0002
-#define FHD_PASSWORD 0x0004
-#define FHD_COMMENT 0x0008
-#define FHD_SOLID 0x0010
-#define FHD_LARGE 0x0100
-#define FHD_UNICODE 0x0200
-#define FHD_SALT 0x0400
-#define FHD_VERSION 0x0800
-#define FHD_EXTTIME 0x1000
-#define FHD_EXTFLAGS 0x2000
+#define FHD_SPLIT_BEFORE 0x0001 /* File continued from previous volume */
+#define FHD_SPLIT_AFTER 0x0002 /* File continued in next volume */
+#define FHD_PASSWORD 0x0004 /* File encrypted with password */
+#define FHD_COMMENT 0x0008 /* File comment present. RAR 3.x uses the separate comment block and does not set this flag. */
+#define FHD_SOLID 0x0010 /* Information from previous files is used (solid flag) (for RAR 2.0 and later) */
+#define FHD_LARGE 0x0100 /* HIGH_PACK_SIZE and HIGH_UNP_SIZE fields are present. These fields are used to archive only very large files (larger than 2Gb), for smaller files these fields are absent. */
+#define FHD_UNICODE 0x0200 /* FILE_NAME contains both usual and encoded Unicode name separated by zero. In this case NAME_SIZE field is equal to the length of usual name plus encoded Unicode name plus 1. If this flag is present, but FILE_NAME does not contain zero bytes, it means that file name is encoded using UTF-8. */
+#define FHD_SALT 0x0400 /* The header contains additional 8 bytes salt after the file name */
+#define FHD_VERSION 0x0800 /* Version flag. It is an old file version, a version number is appended to file name as ';n' */
+#define FHD_EXTTIME 0x1000 /* Extended time field present */
+#define FHD_EXTFLAGS 0x2000 /* This bit always is set, so the complete block size is HEAD_SIZE + PACK_SIZE (and plus HIGH_PACK_SIZE, if bit 0x100 is set) */
/* File dictionary sizes */
#define DICTIONARY_SIZE_64 0x00
@@ -225,6 +225,7 @@ struct rar
mode_t mode;
char *filename;
char *filename_save;
+ size_t filename_save_size;
size_t filename_allocated;
/* File header optional entries */
@@ -1238,6 +1239,20 @@ read_header(struct archive_read *a, stru
crc32_val = crc32(0, (const unsigned char *)p + 2, 7 - 2);
__archive_read_consume(a, 7);
+ if ((rar->file_flags & FHD_SPLIT_BEFORE) && !rar->filename_save)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid RAR entry header: Missing FHD_SPLIT_AFTER for multivolume");
+ return (ARCHIVE_FATAL);
+ }
+
+ if (!(rar->file_flags & FHD_SPLIT_BEFORE) && rar->filename_save)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Invalid RAR entry header: Missing FHD_SPLIT_BEFORE for multivolume");
+ return (ARCHIVE_FATAL);
+ }
+
if (!(rar->file_flags & FHD_SOLID))
{
rar->compression_method = 0;
@@ -1468,7 +1483,7 @@ read_header(struct archive_read *a, stru
}
/* Split file in multivolume RAR. No more need to process header. */
- if (rar->filename_save &&
+ if (rar->file_flags & FHD_SPLIT_BEFORE && rar->filename_save &&
!memcmp(rar->filename, rar->filename_save, filename_size + 1))
{
__archive_read_consume(a, header_size - 7);
@@ -1492,12 +1507,25 @@ read_header(struct archive_read *a, stru
rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
rar->packed_size;
}
+ /* clear filename_save when last multivolume entry */
+ if (!(rar->file_flags & FHD_SPLIT_AFTER))
+ {
+ free(rar->filename_save);
+ rar->filename_save = NULL;
+ rar->filename_save_size = 0;
+ }
+
return ret;
}
- rar->filename_save = (char*)realloc(rar->filename_save,
- filename_size + 1);
- memcpy(rar->filename_save, rar->filename, filename_size + 1);
+ /* Save filename for multivolume */
+ if (rar->file_flags & FHD_SPLIT_AFTER)
+ {
+ rar->filename_save = (char*)realloc(rar->filename_save,
+ filename_size + 1);
+ memcpy(rar->filename_save, rar->filename, filename_size + 1);
+ rar->filename_save_size = filename_size;
+ }
/* Set info for seeking */
free(rar->dbo);