summaryrefslogtreecommitdiff
path: root/libarchive
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@acm.org>2022-08-04 19:30:29 -0700
committerGitHub <noreply@github.com>2022-08-04 19:30:29 -0700
commit2eb700495c4c384cde5c5d4c3e9b9d5d5ca674a8 (patch)
tree47f50b60584151be1ee19bb9399726d008014bb2 /libarchive
parentbd9f5577abf5dc76a3d1d859619404451bc203d2 (diff)
parent267cda9f7647fabddb2c1641d23b8be5b56f4172 (diff)
downloadlibarchive-2eb700495c4c384cde5c5d4c3e9b9d5d5ca674a8.tar.gz
Merge pull request #1745 from bobrofon/rar5-read_data_block
rar5: Fix random initial offset if using archive_read_data_into_fd
Diffstat (limited to 'libarchive')
-rw-r--r--libarchive/archive_read_support_format_rar5.c7
-rw-r--r--libarchive/test/test_read_format_rar5.c25
2 files changed, 31 insertions, 1 deletions
diff --git a/libarchive/archive_read_support_format_rar5.c b/libarchive/archive_read_support_format_rar5.c
index a3cfa72e..cc966a51 100644
--- a/libarchive/archive_read_support_format_rar5.c
+++ b/libarchive/archive_read_support_format_rar5.c
@@ -3911,6 +3911,13 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
case GOOD:
/* fallthrough */
case BEST:
+ /* No data is returned here. But because a sparse-file aware
+ * caller (like archive_read_data_into_fd) may treat zero-size
+ * as a sparse file block, we need to update the offset
+ * accordingly. At this point the decoder doesn't have any
+ * pending uncompressed data blocks, so the current position in
+ * the output file should be last_write_ptr. */
+ if (offset) *offset = rar->cstate.last_write_ptr;
return uncompress_file(a);
default:
archive_set_error(&a->archive,
diff --git a/libarchive/test/test_read_format_rar5.c b/libarchive/test/test_read_format_rar5.c
index acc90510..0c302897 100644
--- a/libarchive/test/test_read_format_rar5.c
+++ b/libarchive/test/test_read_format_rar5.c
@@ -1346,4 +1346,27 @@ DEFINE_TEST(test_read_format_rar5_bad_window_size_in_multiarchive_file)
while(0 < archive_read_data(a, buf, sizeof(buf))) {}
EPILOGUE();
-} \ No newline at end of file
+}
+
+DEFINE_TEST(test_read_format_rar5_read_data_block_uninitialized_offset)
+{
+ const void *buf;
+ size_t size;
+ la_int64_t offset;
+
+ PROLOGUE("test_read_format_rar5_compressed.rar");
+ assertA(0 == archive_read_next_header(a, &ae));
+
+ /* A real code may pass a pointer to an uninitialized variable as an offset
+ * output argument. Here we want to check this situation. But because
+ * relying on a value of an uninitialized variable in a test is not a good
+ * idea, let's pretend that 0xdeadbeef is a random value of the
+ * uninitialized variable. */
+ offset = 0xdeadbeef;
+ assertEqualInt(ARCHIVE_OK, archive_read_data_block(a, &buf, &size, &offset));
+ /* The test archive doesn't contain a sparse file. And because of that, here
+ * we assume that the first returned offset should be 0. */
+ assertEqualInt(0, offset);
+
+ EPILOGUE();
+}