From: Tobias Stoeckmann Date: Tue, 27 May 2025 19:08:55 +0000 (+0200) Subject: tar: Handle many sparse comments on 32 bit systems X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2646%2Fhead;p=thirdparty%2Flibarchive.git tar: Handle many sparse comments on 32 bit systems The sparse 1.0 parser skips lines with comments. The amount of skipped bytes is stored in a ssize_t variable, although common 32 bit systems allow files larger than 4 GB. Gracefully handle files with more than 2 GB bytes full of comments to prevent integer truncations. Signed-off-by: Tobias Stoeckmann --- diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 1cc667169..1f239d8e5 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -174,7 +174,7 @@ static int gnu_sparse_old_parse(struct archive_read *, struct tar *, const struct gnu_sparse *sparse, int length); static int gnu_sparse_01_parse(struct archive_read *, struct tar *, const char *, size_t); -static ssize_t gnu_sparse_10_read(struct archive_read *, struct tar *, +static int64_t gnu_sparse_10_read(struct archive_read *, struct tar *, int64_t *); static int header_Solaris_ACL(struct archive_read *, struct tar *, struct archive_entry *, const void *, int64_t *); @@ -3247,12 +3247,10 @@ gnu_sparse_10_atol(struct archive_read *a, struct tar *tar, * Returns length (in bytes) of the sparse data description * that was read. */ -static ssize_t +static int64_t gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) { - ssize_t bytes_read; - int entries; - int64_t offset, size, to_skip, remaining; + int64_t bytes_read, entries, offset, size, to_skip, remaining; /* Clear out the existing sparse list. */ gnu_clear_sparse_list(tar); @@ -3260,7 +3258,7 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) remaining = tar->entry_bytes_remaining; /* Parse entries. */ - entries = (int)gnu_sparse_10_atol(a, tar, &remaining, unconsumed); + entries = gnu_sparse_10_atol(a, tar, &remaining, unconsumed); if (entries < 0) return (ARCHIVE_FATAL); /* Parse the individual entries. */ @@ -3278,14 +3276,14 @@ gnu_sparse_10_read(struct archive_read *a, struct tar *tar, int64_t *unconsumed) } /* Skip rest of block... */ tar_flush_unconsumed(a, unconsumed); - bytes_read = (ssize_t)(tar->entry_bytes_remaining - remaining); + bytes_read = tar->entry_bytes_remaining - remaining; to_skip = 0x1ff & -bytes_read; /* Fail if tar->entry_bytes_remaing would get negative */ if (to_skip > remaining) return (ARCHIVE_FATAL); if (to_skip != __archive_read_consume(a, to_skip)) return (ARCHIVE_FATAL); - return ((ssize_t)(bytes_read + to_skip)); + return (bytes_read + to_skip); } /*