Imported Upstream version 3.23.2
[platform/upstream/cmake.git] / Utilities / cmlibarchive / libarchive / archive_read_support_format_rar5.c
index 3131955..855317a 100644 (file)
@@ -1012,7 +1012,16 @@ static int read_var_sized(struct archive_read* a, size_t* pvalue,
        return ret;
 }
 
-static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
+static int read_bits_32(struct archive_read* a, struct rar5* rar,
+       const uint8_t* p, uint32_t* value)
+{
+       if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
+               archive_set_error(&a->archive,
+                       ARCHIVE_ERRNO_PROGRAMMER,
+                       "Premature end of stream during extraction of data (#1)");
+               return ARCHIVE_FATAL;
+       }
+
        uint32_t bits = ((uint32_t) p[rar->bits.in_addr]) << 24;
        bits |= p[rar->bits.in_addr + 1] << 16;
        bits |= p[rar->bits.in_addr + 2] << 8;
@@ -1023,7 +1032,16 @@ static int read_bits_32(struct rar5* rar, const uint8_t* p, uint32_t* value) {
        return ARCHIVE_OK;
 }
 
-static int read_bits_16(struct rar5* rar, const uint8_t* p, uint16_t* value) {
+static int read_bits_16(struct archive_read* a, struct rar5* rar,
+       const uint8_t* p, uint16_t* value)
+{
+       if(rar->bits.in_addr >= rar->cstate.cur_block_size) {
+               archive_set_error(&a->archive,
+                       ARCHIVE_ERRNO_PROGRAMMER,
+                       "Premature end of stream during extraction of data (#2)");
+               return ARCHIVE_FATAL;
+       }
+
        int bits = (int) ((uint32_t) p[rar->bits.in_addr]) << 16;
        bits |= (int) p[rar->bits.in_addr + 1] << 8;
        bits |= (int) p[rar->bits.in_addr + 2];
@@ -1039,8 +1057,8 @@ static void skip_bits(struct rar5* rar, int bits) {
 }
 
 /* n = up to 16 */
-static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
-    int* value)
+static int read_consume_bits(struct archive_read* a, struct rar5* rar,
+       const uint8_t* p, int n, int* value)
 {
        uint16_t v;
        int ret, num;
@@ -1051,7 +1069,7 @@ static int read_consume_bits(struct rar5* rar, const uint8_t* p, int n,
                return ARCHIVE_FATAL;
        }
 
-       ret = read_bits_16(rar, p, &v);
+       ret = read_bits_16(a, rar, p, &v);
        if(ret != ARCHIVE_OK)
                return ret;
 
@@ -1712,14 +1730,29 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
                }
        }
 
-       /* 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->cstate.window_size < (ssize_t) window_size &&
+           rar->cstate.window_buf)
+       {
+               /* If window_buf has been allocated before, reallocate it, so
+                * that its size will match new window_size. */
+
+               uint8_t* new_window_buf =
+                       realloc(rar->cstate.window_buf, window_size);
+
+               if(!new_window_buf) {
+                       archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+                               "Not enough memory when trying to realloc the window "
+                               "buffer.");
+                       return ARCHIVE_FATAL;
+               }
+
+               rar->cstate.window_buf = new_window_buf;
        }
 
+       /* 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
@@ -2425,13 +2458,13 @@ static int create_decode_tables(uint8_t* bit_length,
 static int decode_number(struct archive_read* a, struct decode_table* table,
     const uint8_t* p, uint16_t* num)
 {
-       int i, bits, dist;
+       int i, bits, dist, ret;
        uint16_t bitfield;
        uint32_t pos;
        struct rar5* rar = get_context(a);
 
-       if(ARCHIVE_OK != read_bits_16(rar, p, &bitfield)) {
-               return ARCHIVE_EOF;
+       if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &bitfield))) {
+               return ret;
        }
 
        bitfield &= 0xfffe;
@@ -2537,14 +2570,6 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        for(i = 0; i < HUFF_TABLE_SIZE;) {
                uint16_t num;
 
-               if((rar->bits.in_addr + 6) >= rar->cstate.cur_block_size) {
-                       /* Truncated data, can't continue. */
-                       archive_set_error(&a->archive,
-                           ARCHIVE_ERRNO_FILE_FORMAT,
-                           "Truncated data in huffman tables (#2)");
-                       return ARCHIVE_FATAL;
-               }
-
                ret = decode_number(a, &rar->cstate.bd, p, &num);
                if(ret != ARCHIVE_OK) {
                        archive_set_error(&a->archive,
@@ -2561,8 +2586,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
                        /* 16..17: repeat previous code */
                        uint16_t n;
 
-                       if(ARCHIVE_OK != read_bits_16(rar, p, &n))
-                               return ARCHIVE_EOF;
+                       if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
+                               return ret;
 
                        if(num == 16) {
                                n >>= 13;
@@ -2590,8 +2615,8 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
                        /* other codes: fill with zeroes `n` times */
                        uint16_t n;
 
-                       if(ARCHIVE_OK != read_bits_16(rar, p, &n))
-                               return ARCHIVE_EOF;
+                       if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &n)))
+                               return ret;
 
                        if(num == 18) {
                                n >>= 13;
@@ -2707,22 +2732,22 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
 }
 
 /* Convenience function used during filter processing. */
-static int parse_filter_data(struct rar5* rar, const uint8_t* p,
-    uint32_t* filter_data)
+static int parse_filter_data(struct archive_read* a, struct rar5* rar,
+       const uint8_t* p, uint32_t* filter_data)
 {
-       int i, bytes;
+       int i, bytes, ret;
        uint32_t data = 0;
 
-       if(ARCHIVE_OK != read_consume_bits(rar, p, 2, &bytes))
-               return ARCHIVE_EOF;
+       if(ARCHIVE_OK != (ret = read_consume_bits(a, rar, p, 2, &bytes)))
+               return ret;
 
        bytes++;
 
        for(i = 0; i < bytes; i++) {
                uint16_t byte;
 
-               if(ARCHIVE_OK != read_bits_16(rar, p, &byte)) {
-                       return ARCHIVE_EOF;
+               if(ARCHIVE_OK != (ret = read_bits_16(a, rar, p, &byte))) {
+                       return ret;
                }
 
                /* Cast to uint32_t will ensure the shift operation will not
@@ -2765,16 +2790,17 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
        uint16_t filter_type;
        struct filter_info* filt = NULL;
        struct rar5* rar = get_context(ar);
+       int ret;
 
        /* Read the parameters from the input stream. */
-       if(ARCHIVE_OK != parse_filter_data(rar, p, &block_start))
-               return ARCHIVE_EOF;
+       if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_start)))
+               return ret;
 
-       if(ARCHIVE_OK != parse_filter_data(rar, p, &block_length))
-               return ARCHIVE_EOF;
+       if(ARCHIVE_OK != (ret = parse_filter_data(ar, rar, p, &block_length)))
+               return ret;
 
-       if(ARCHIVE_OK != read_bits_16(rar, p, &filter_type))
-               return ARCHIVE_EOF;
+       if(ARCHIVE_OK != (ret = read_bits_16(ar, rar, p, &filter_type)))
+               return ret;
 
        filter_type >>= 13;
        skip_bits(rar, 3);
@@ -2814,8 +2840,8 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
        if(filter_type == FILTER_DELTA) {
                int channels;
 
-               if(ARCHIVE_OK != read_consume_bits(rar, p, 5, &channels))
-                       return ARCHIVE_EOF;
+               if(ARCHIVE_OK != (ret = read_consume_bits(ar, rar, p, 5, &channels)))
+                       return ret;
 
                filt->channels = channels + 1;
        }
@@ -2823,10 +2849,11 @@ static int parse_filter(struct archive_read* ar, const uint8_t* p) {
        return ARCHIVE_OK;
 }
 
-static int decode_code_length(struct rar5* rar, const uint8_t* p,
-    uint16_t code)
+static int decode_code_length(struct archive_read* a, struct rar5* rar,
+       const uint8_t* p, uint16_t code)
 {
        int lbits, length = 2;
+
        if(code < 8) {
                lbits = 0;
                length += code;
@@ -2838,7 +2865,7 @@ static int decode_code_length(struct rar5* rar, const uint8_t* p,
        if(lbits > 0) {
                int add;
 
-               if(ARCHIVE_OK != read_consume_bits(rar, p, lbits, &add))
+               if(ARCHIVE_OK != read_consume_bits(a, rar, p, lbits, &add))
                        return -1;
 
                length += add;
@@ -2933,7 +2960,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                        continue;
                } else if(num >= 262) {
                        uint16_t dist_slot;
-                       int len = decode_code_length(rar, p, num - 262),
+                       int len = decode_code_length(a, rar, p, num - 262),
                                dbits,
                                dist = 1;
 
@@ -2975,12 +3002,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                        uint16_t low_dist;
 
                                        if(dbits > 4) {
-                                               if(ARCHIVE_OK != read_bits_32(
-                                                   rar, p, &add)) {
+                                               if(ARCHIVE_OK != (ret = read_bits_32(
+                                                   a, rar, p, &add))) {
                                                        /* Return EOF if we
                                                         * can't read more
                                                         * data. */
-                                                       return ARCHIVE_EOF;
+                                                       return ret;
                                                }
 
                                                skip_bits(rar, dbits - 4);
@@ -3015,11 +3042,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                        /* dbits is one of [0,1,2,3] */
                                        int add;
 
-                                       if(ARCHIVE_OK != read_consume_bits(rar,
-                                            p, dbits, &add)) {
+                                       if(ARCHIVE_OK != (ret = read_consume_bits(a, rar,
+                                            p, dbits, &add))) {
                                                /* Return EOF if we can't read
                                                 * more data. */
-                                               return ARCHIVE_EOF;
+                                               return ret;
                                        }
 
                                        dist += add;
@@ -3076,7 +3103,11 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                return ARCHIVE_FATAL;
                        }
 
-                       len = decode_code_length(rar, p, len_slot);
+                       len = decode_code_length(a, rar, p, len_slot);
+                       if (len == -1) {
+                               return ARCHIVE_FATAL;
+                       }
+
                        rar->cstate.last_len = len;
 
                        if(ARCHIVE_OK != copy_string(a, len, dist))
@@ -3600,6 +3631,16 @@ static int do_uncompress_file(struct archive_read* a) {
                rar->cstate.initialized = 1;
        }
 
+       /* Don't allow extraction if window_size is invalid. */
+       if(rar->cstate.window_size == 0) {
+               archive_set_error(&a->archive,
+                       ARCHIVE_ERRNO_FILE_FORMAT,
+                       "Invalid window size declaration in this file");
+
+               /* This should never happen in valid files. */
+               return ARCHIVE_FATAL;
+       }
+
        if(rar->cstate.all_filters_applied == 1) {
                /* We use while(1) here, but standard case allows for just 1
                 * iteration. The loop will iterate if process_block() didn't
@@ -4076,6 +4117,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
        if(ARCHIVE_OK != rar5_init(rar)) {
                archive_set_error(&ar->archive, ENOMEM,
                    "Can't allocate rar5 filter buffer");
+               free(rar);
                return ARCHIVE_FATAL;
        }