From 5289c868637f8ddecb170d299e9c4b4bd659f68a Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Sun, 20 Aug 2023 20:41:24 +0200 Subject: [PATCH 1/2] file_iterator: always map at least one block. This is needed for consistent behavior between implementations that ignore desired_size and implementations that honor it. --- lib/file/file_iterator.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/file/file_iterator.c b/lib/file/file_iterator.c index 2e8b0fac2..6aaee3896 100644 --- a/lib/file/file_iterator.c +++ b/lib/file/file_iterator.c @@ -135,16 +135,12 @@ map_block_uncompressed( size_t desired_size) { int rv = 0; const struct SqshFile *file = iterator->file; - sqsh_index_t block_index = iterator->block_index; struct SqshMapReader *reader = &iterator->map_reader; - if (rv < 0) { - goto out; - } - const uint64_t block_count = sqsh_file_block_count(file); uint64_t outer_size = 0; const size_t remaining_direct = sqsh__map_reader_remaining_direct(reader); + for (; iterator->sparse_size == 0 && block_index < block_count; block_index++) { if (sqsh_file_block_is_compressed(file, block_index)) { @@ -277,6 +273,14 @@ sqsh_file_iterator_next( sqsh__extract_view_cleanup(&iterator->extract_view); + // Desired size of 0 would result in a noop for uncompressed blocks, + // resulting in inconsistend behavior depending whether the block is + // compressed, which ignores the desired size, or uncompressed, which + // honors the desired size. + if (desired_size == 0) { + desired_size = 1; + } + if (iterator->sparse_size > 0) { return map_zero_block(iterator); } else if (iterator->block_index < block_count) { From d32ea29f60838878312e9f7d61f0bfef361a2350 Mon Sep 17 00:00:00 2001 From: Enno Boland Date: Sun, 20 Aug 2023 23:16:49 +0200 Subject: [PATCH 2/2] tools/fs-common.c: workaround error at end of file OpenBSD requests a chunk of data at the end of the file. Currently sqsh_file_reader_advance() returns an error in this case. This commit works around this behavior by returning early when zero size is requested. --- tools/fs-common.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/fs-common.c b/tools/fs-common.c index 5e27fb454..01d3f570f 100644 --- a/tools/fs-common.c +++ b/tools/fs-common.c @@ -145,6 +145,15 @@ fs_common_read( size = file_size - offset; } + + // This works around a bug in sqsh_file_reader_advance: + // Reading a 0 size at the end of the file will return + // SQSH_ERROR_OUT_OF_BOUNDS. This should succeed instead, + // providing an empty buffer. + if (size == 0) { + return 0; + } + rv = sqsh_file_reader_advance(*reader, offset, size); if (rv < 0) { goto out;