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) { 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;