aboutsummaryrefslogtreecommitdiffstats
path: root/libarchive/archive_read_support_format_rar5.c
diff options
context:
space:
mode:
Diffstat (limited to 'libarchive/archive_read_support_format_rar5.c')
-rw-r--r--libarchive/archive_read_support_format_rar5.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c
index e58cbbf6d829..ce38b1fc990f 100644
--- a/libarchive/archive_read_support_format_rar5.c
+++ b/libarchive/archive_read_support_format_rar5.c
@@ -63,6 +63,7 @@
#if defined DEBUG
#define DEBUG_CODE if(1)
+#define LOG(...) do { printf("rar5: " __VA_ARGS__); puts(""); } while(0)
#else
#define DEBUG_CODE if(0)
#endif
@@ -115,6 +116,8 @@ struct file_header {
/* Optional redir fields */
uint64_t redir_type;
uint64_t redir_flags;
+
+ ssize_t solid_window_size; /* Used in file format check. */
};
enum EXTRA {
@@ -1177,7 +1180,7 @@ static int process_main_locator_extra_block(struct archive_read* a,
static int parse_file_extra_hash(struct archive_read* a, struct rar5* rar,
ssize_t* extra_data_size)
{
- size_t hash_type;
+ size_t hash_type = 0;
size_t value_len;
if(!read_var_sized(a, &hash_type, &value_len))
@@ -1303,7 +1306,7 @@ static int parse_file_extra_htime(struct archive_read* a,
struct archive_entry* e, struct rar5* rar, ssize_t* extra_data_size)
{
char unix_time = 0;
- size_t flags;
+ size_t flags = 0;
size_t value_len;
enum HTIME_FLAGS {
@@ -1665,6 +1668,17 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
g_unpack_window_size << ((compression_info >> 10) & 15);
rar->cstate.method = c_method;
rar->cstate.version = c_version + 50;
+ rar->file.solid = (compression_info & SOLID) > 0;
+
+ /* Archives which declare solid files without initializing the window
+ * buffer first are invalid. */
+
+ if(rar->file.solid > 0 && rar->cstate.window_buf == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Declared solid file, but no window buffer "
+ "initialized yet.");
+ return ARCHIVE_FATAL;
+ }
/* Check if window_size is a sane value. Also, if the file is not
* declared as a directory, disallow window_size == 0. */
@@ -1676,12 +1690,36 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
return ARCHIVE_FATAL;
}
- /* Values up to 64M should fit into ssize_t on every
- * architecture. */
- rar->cstate.window_size = (ssize_t) window_size;
+ if(rar->file.solid > 0) {
+ /* Re-check if current window size is the same as previous
+ * window size (for solid files only). */
+ if(rar->file.solid_window_size > 0 &&
+ rar->file.solid_window_size != (ssize_t) window_size)
+ {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Window size for this solid file doesn't match "
+ "the window size used in previous solid file. ");
+ return ARCHIVE_FATAL;
+ }
+ }
+
+ /* If we're currently switching volumes, ignore the new definition of
+ * window_size. */
+ if(rar->cstate.switch_multivolume == 0) {
+ /* Values up to 64M should fit into ssize_t on every
+ * architecture. */
+ rar->cstate.window_size = (ssize_t) window_size;
+ }
+
+ if(rar->file.solid > 0 && rar->file.solid_window_size == 0) {
+ /* Solid files have to have the same window_size across
+ whole archive. Remember the window_size parameter
+ for first solid file found. */
+ rar->file.solid_window_size = rar->cstate.window_size;
+ }
+
init_window_mask(rar);
- rar->file.solid = (compression_info & SOLID) > 0;
rar->file.service = 0;
if(!read_var_sized(a, &host_os, NULL))