]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
rar5: don't continue if the last block produced no data (#2105)
authorDuncan Horn <40036384+dunhor@users.noreply.github.com>
Mon, 1 Apr 2024 18:13:19 +0000 (11:13 -0700)
committerGitHub <noreply@github.com>
Mon, 1 Apr 2024 18:13:19 +0000 (20:13 +0200)
There appear to be RAR5 archives out in the wild that have blocks at the
end of files that don't produce any data. The code in libarchive has an
infinite loop that won't break until it processes a block that produces
data, which will end up reading past the end of the file if the last
block in the file produces no data.

libarchive/archive_read_support_format_rar5.c

index 1f909943941251983d07ec54cc22c80f17a44e2f..e8846a5b0d0d40193af40c0e905495e48006ec39 100644 (file)
@@ -495,6 +495,11 @@ uint8_t bf_is_table_present(const struct compressed_block_header* hdr) {
        return (hdr->block_flags_u8 >> 7) & 1;
 }
 
+static inline
+uint8_t bf_is_last_block(const struct compressed_block_header* hdr) {
+       return (hdr->block_flags_u8 >> 6) & 1;
+}
+
 static inline struct rar5* get_context(struct archive_read* a) {
        return (struct rar5*) a->format->data;
 }
@@ -3757,7 +3762,12 @@ static int do_uncompress_file(struct archive_read* a) {
                        if(rar->cstate.last_write_ptr ==
                            rar->cstate.write_ptr) {
                                /* The block didn't generate any new data,
-                                * so just process a new block. */
+                                * so just process a new block if this one
+                                * wasn't the last block in the file. */
+                               if (bf_is_last_block(&rar->last_block_hdr)) {
+                                       return ARCHIVE_EOF;
+                               }
+
                                continue;
                        }