]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
rar5: convert remaining per-entry data errors to ARCHIVE_FAILED
authorTim Kientzle <kientzle@acm.org>
Mon, 4 May 2026 03:12:42 +0000 (20:12 -0700)
committerTim Kientzle <kientzle@acm.org>
Tue, 5 May 2026 20:39:27 +0000 (13:39 -0700)
Follow-up to 9fa772ab.  An audit of the rar5 reader found many more
ARCHIVE_FATAL returns in data-decode paths that should be ARCHIVE_FAILED
so the caller can move on to the next entry after a corrupt one:

  apply_filters       Unsupported filter type
  parse_tables        Truncated huffman tables, decode failures (8 sites)
  parse_block_header  Unsupported header size, block checksum error
  do_uncompress_block Decode code length / distance slot failures
                      Distance pointer overflow
                      decode_number / decode_code_length failures
  merge_block         Block size == 0 during merge
  do_uncompress_file  Invalid window size declaration
  verify_checksums    CRC32 / BLAKE2 mismatch

Programmer assertions, ENOMEM, true I/O errors, and propagation of
copy_string's window-buf-NULL FATAL return are intentionally kept as
ARCHIVE_FATAL because they are not recoverable per-entry conditions.

libarchive/archive_read_support_format_rar5.c

index 9b263110c9a3d010b9f2fab1c5e274baf0d476dd..6e5656b8fc21c9af6b23ef9340632b090c94b3f2 100644 (file)
@@ -700,7 +700,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) {
                            ARCHIVE_ERRNO_FILE_FORMAT,
                            "Unsupported filter type: 0x%x",
                            (unsigned int)flt->type);
-                       return ARCHIVE_FATAL;
+                       return ARCHIVE_FAILED;
        }
 
        if(ret != ARCHIVE_OK) {
@@ -2748,7 +2748,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
                        archive_set_error(&a->archive,
                            ARCHIVE_ERRNO_FILE_FORMAT,
                            "Truncated data in huffman tables");
-                       return ARCHIVE_FATAL;
+                       return ARCHIVE_FAILED;
                }
 
                value = (p[i] & nibble_mask) >> nibble_shift;
@@ -2794,7 +2794,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        if(ret != ARCHIVE_OK) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                    "Decoding huffman tables failed");
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        for(i = 0; i < HUFF_TABLE_SIZE;) {
@@ -2805,7 +2805,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
                        archive_set_error(&a->archive,
                            ARCHIVE_ERRNO_FILE_FORMAT,
                            "Decoding huffman tables failed");
-                       return ARCHIVE_FATAL;
+                       return ARCHIVE_FAILED;
                }
 
                if(num < 16) {
@@ -2839,7 +2839,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
                                    ARCHIVE_ERRNO_FILE_FORMAT,
                                    "Unexpected error when decoding "
                                    "huffman tables");
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
                        }
                } else {
                        /* other codes: fill with zeroes `n` times */
@@ -2867,7 +2867,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        if(ret != ARCHIVE_OK) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                     "Failed to create literal table");
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        idx += HUFF_NC;
@@ -2876,7 +2876,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        if(ret != ARCHIVE_OK) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                    "Failed to create distance table");
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        idx += HUFF_DC;
@@ -2885,7 +2885,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        if(ret != ARCHIVE_OK) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                    "Failed to create lower bits of distances table");
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        idx += HUFF_LDC;
@@ -2894,7 +2894,7 @@ static int parse_tables(struct archive_read* a, struct rar5* rar,
        if(ret != ARCHIVE_OK) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                    "Failed to create repeating distances table");
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        return ARCHIVE_OK;
@@ -2912,7 +2912,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
                    "Unsupported block header size (was %d, max is 2)",
                    bf_byte_count(hdr));
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        /* This should probably use bit reader interface in order to be more
@@ -2956,7 +2956,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
                    "Block checksum error: got 0x%x, expected 0x%x",
                    hdr->block_cksum, calculated_cksum);
 
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
 #endif
        }
 
@@ -3203,7 +3203,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                    ARCHIVE_ERRNO_PROGRAMMER,
                                    "Failed to decode the code length");
 
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
                        }
 
                        if(ARCHIVE_OK != decode_number(a, &rar->cstate.dd, p,
@@ -3213,7 +3213,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                    ARCHIVE_ERRNO_PROGRAMMER,
                                    "Failed to decode the distance slot");
 
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
                        }
 
                        if(dist_slot < 4) {
@@ -3258,7 +3258,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                                    "Failed to decode the "
                                                    "distance slot");
 
-                                               return ARCHIVE_FATAL;
+                                               return ARCHIVE_FAILED;
                                        }
 
                                        if(dist >= INT_MAX - low_dist - 1) {
@@ -3268,7 +3268,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
                                                    ARCHIVE_ERRNO_FILE_FORMAT,
                                                    "Distance pointer "
                                                    "overflow");
-                                               return ARCHIVE_FATAL;
+                                               return ARCHIVE_FAILED;
                                        }
 
                                        dist += low_dist;
@@ -3334,12 +3334,12 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
 
                        if(ARCHIVE_OK != decode_number(a, &rar->cstate.rd, p,
                            &len_slot)) {
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
                        }
 
                        len = decode_code_length(a, rar, p, len_slot);
                        if (len == -1) {
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
                        }
 
                        rar->cstate.last_len = len;
@@ -3528,7 +3528,7 @@ static int merge_block(struct archive_read* a, ssize_t block_size,
                        archive_set_error(&a->archive,
                            ARCHIVE_ERRNO_FILE_FORMAT,
                            "Encountered block size == 0 during block merge");
-                       return ARCHIVE_FATAL;
+                       return ARCHIVE_FAILED;
                }
 
                if(!read_ahead(a, cur_block_size, &lp))
@@ -3876,7 +3876,7 @@ static int do_uncompress_file(struct archive_read* a) {
                        "Invalid window size declaration in this file");
 
                /* This should never happen in valid files. */
-               return ARCHIVE_FATAL;
+               return ARCHIVE_FAILED;
        }
 
        if(rar->cstate.all_filters_applied == 1) {
@@ -4131,7 +4131,7 @@ static int verify_checksums(struct archive_read* a) {
                                archive_set_error(&a->archive,
                                    ARCHIVE_ERRNO_FILE_FORMAT,
                                    "Checksum error: CRC32");
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
 #endif
                        } else {
                                DEBUG_CODE {
@@ -4166,7 +4166,7 @@ static int verify_checksums(struct archive_read* a) {
                                    ARCHIVE_ERRNO_FILE_FORMAT,
                                    "Checksum error: BLAKE2");
 
-                               return ARCHIVE_FATAL;
+                               return ARCHIVE_FAILED;
 #endif
                        }
                }