diff options
Diffstat (limited to 'src/libs/3rdparty/libarchive/archive_read_support_format_rar.c')
-rw-r--r-- | src/libs/3rdparty/libarchive/archive_read_support_format_rar.c | 72 |
1 files changed, 53 insertions, 19 deletions
diff --git a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c index 893a280ff..f9cbe2a88 100644 --- a/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c +++ b/src/libs/3rdparty/libarchive/archive_read_support_format_rar.c @@ -430,7 +430,7 @@ static int new_node(struct huffman_code *); static int make_table(struct archive_read *, struct huffman_code *); static int make_table_recurse(struct archive_read *, struct huffman_code *, int, struct huffman_table_entry *, int, int); -static int64_t expand(struct archive_read *, int64_t); +static int expand(struct archive_read *, int64_t *); static int copy_from_lzss_window_to_unp(struct archive_read *, const void **, int64_t, int); static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *); @@ -1988,7 +1988,7 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, return (ARCHIVE_FATAL); struct rar *rar; - int64_t start, end, actualend; + int64_t start, end; size_t bs; int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i; @@ -2179,11 +2179,12 @@ read_data_compressed(struct archive_read *a, const void **buff, size_t *size, end = rar->filters.filterstart; } - if ((actualend = expand(a, end)) < 0) - return ((int)actualend); + ret = expand(a, &end); + if (ret != ARCHIVE_OK) + return (ret); - rar->bytes_uncopied = actualend - start; - rar->filters.lastend = actualend; + rar->bytes_uncopied = end - start; + rar->filters.lastend = end; if (rar->filters.lastend != rar->filters.filterstart && rar->bytes_uncopied == 0) { /* Broken RAR files cause this case. * NOTE: If this case were possible on a normal RAR file @@ -2825,8 +2826,8 @@ make_table_recurse(struct archive_read *a, struct huffman_code *code, int node, return ret; } -static int64_t -expand(struct archive_read *a, int64_t end) +static int +expand(struct archive_read *a, int64_t *end) { static const unsigned char lengthbases[] = { 0, 1, 2, 3, 4, 5, 6, @@ -2873,16 +2874,19 @@ expand(struct archive_read *a, int64_t end) struct rar *rar = (struct rar *)(a->format->data); struct rar_br *br = &(rar->br); - if (rar->filters.filterstart < end) - end = rar->filters.filterstart; + if (rar->filters.filterstart < *end) + *end = rar->filters.filterstart; while (1) { - if(lzss_position(&rar->lzss) >= end) - return end; + if(lzss_position(&rar->lzss) >= *end) { + return (ARCHIVE_OK); + } - if(rar->is_ppmd_block) - return lzss_position(&rar->lzss); + if(rar->is_ppmd_block) { + *end = lzss_position(&rar->lzss); + return (ARCHIVE_OK); + } if ((symbol = read_next_symbol(a, &rar->maincode)) < 0) return (ARCHIVE_FATAL); @@ -2906,7 +2910,8 @@ expand(struct archive_read *a, int64_t end) goto truncated_data; rar->start_new_table = rar_br_bits(br, 1); rar_br_consume(br, 1); - return lzss_position(&rar->lzss); + *end = lzss_position(&rar->lzss); + return (ARCHIVE_OK); } else { @@ -2917,7 +2922,7 @@ expand(struct archive_read *a, int64_t end) } else if(symbol==257) { - if (!read_filter(a, &end)) + if (!read_filter(a, end)) return (ARCHIVE_FATAL); continue; } @@ -3323,14 +3328,43 @@ run_filters(struct archive_read *a) struct rar *rar = (struct rar *)(a->format->data); struct rar_filters *filters = &rar->filters; struct rar_filter *filter = filters->stack; - size_t start = filters->filterstart; - size_t end = start + filter->blocklength; + struct rar_filter *f; + size_t start, end; + int64_t tend; uint32_t lastfilteraddress; uint32_t lastfilterlength; int ret; + if (filters == NULL || filter == NULL) + return (0); + + start = filters->filterstart; + end = start + filter->blocklength; + filters->filterstart = INT64_MAX; - end = (size_t)expand(a, end); + tend = (int64_t)end; + ret = expand(a, &tend); + if (ret != ARCHIVE_OK) + return 0; + + /* Check if filter stack was modified in expand() */ + ret = ARCHIVE_FATAL; + f = filters->stack; + while (f) + { + if (f == filter) + { + ret = ARCHIVE_OK; + break; + } + f = f->next; + } + if (ret != ARCHIVE_OK) + return 0; + + if (tend < 0) + return 0; + end = (size_t)tend; if (end != start + filter->blocklength) return 0; |