diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2019-10-04 12:31:32 -0700 |
---|---|---|
committer | Daniel Verkamp <dverkamp@chromium.org> | 2019-10-04 16:41:01 -0700 |
commit | e9f5e7081c62a47fb875569403e37cacca26dc12 (patch) | |
tree | b5242099c5ff98332be1074d4b80b168ee96bc0b /libarchive/archive_read_disk_posix.c | |
parent | ebef6c495e8d843523503a42c406fc5ff3ef8914 (diff) | |
download | libarchive-e9f5e7081c62a47fb875569403e37cacca26dc12.tar.gz |
Fix sparse file offset overflow on 32-bit systems
On architectures where ssize_t is 32 bits but file offsets are 64 bits
(such as 32-bit Linux with _FILE_OFFSET_BITS=64), the POSIX disk reader
would incorrectly skip large sparse regions due to a 32-bit integer
overflow in _archive_read_data_block(). This can result in the reader
failing with "Encountered out-of-order sparse blocks", since the
overflowed value is interpreted as a signed number and added to the
current offset.
The bytes variable was used to store the difference between two 64-bit
integers, but bytes is a ssize_t. Since this value of bytes was not
used after the block handling sparse offsets (it is always overwritten
in the block below), replace it with an int64_t sparse_bytes variable
that can always represent the difference without truncation.
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'libarchive/archive_read_disk_posix.c')
-rw-r--r-- | libarchive/archive_read_disk_posix.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 87963c3c..f62d182e 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -694,6 +694,7 @@ _archive_read_data_block(struct archive *_a, const void **buff, struct tree *t = a->tree; int r; ssize_t bytes; + int64_t sparse_bytes; size_t buffbytes; int empty_sparse_region = 0; @@ -792,9 +793,9 @@ _archive_read_data_block(struct archive *_a, const void **buff, a->archive.state = ARCHIVE_STATE_FATAL; goto abort_read_data; } - bytes = t->current_sparse->offset - t->entry_total; - t->entry_remaining_bytes -= bytes; - t->entry_total += bytes; + sparse_bytes = t->current_sparse->offset - t->entry_total; + t->entry_remaining_bytes -= sparse_bytes; + t->entry_total += sparse_bytes; } /* |