From: GeorgH93 Date: Mon, 15 Jun 2026 21:21:52 +0000 (+0200) Subject: Fix reading bzip2 zipx with ZIP_LENGTH_AT_END flag from non-seekable stream X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=369084a4f7c9a71fbacda2a034db8772a9ea06c5;p=thirdparty%2Flibarchive.git Fix reading bzip2 zipx with ZIP_LENGTH_AT_END flag from non-seekable stream --- diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 7f21220a6..0f623edc6 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -2540,7 +2540,7 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, size_t *size, int64_t *offset) { struct zip *zip = (struct zip *)(a->format->data); - ssize_t bytes_avail = 0, in_bytes, to_consume; + ssize_t bytes_avail = 0, to_consume; const void *compressed_buff; const void *sp; int r; @@ -2557,30 +2557,26 @@ zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff, /* Fetch more compressed bytes. */ compressed_buff = __archive_read_ahead(a, 1, &bytes_avail); - if(bytes_avail < 0) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, - "Truncated bzip2 file body"); - return (ARCHIVE_FATAL); + if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) + && bytes_avail > zip->entry_bytes_remaining) { + bytes_avail = (ssize_t)zip->entry_bytes_remaining; } - - in_bytes = (ssize_t)zipmin(zip->entry_bytes_remaining, bytes_avail); - if(in_bytes < 1) { + if(bytes_avail < 1) { /* libbz2 doesn't complain when caller feeds avail_in == 0. * It will actually return success in this case, which is * undesirable. This is why we need to make this check * manually. */ - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Truncated bzip2 file body"); return (ARCHIVE_FATAL); } - zip_read_decrypt(zip, compressed_buff, in_bytes, - &compressed_buff, &in_bytes, &sp); + zip_read_decrypt(zip, compressed_buff, bytes_avail, + &compressed_buff, &bytes_avail, &sp); /* Setup buffer boundaries. */ zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff; - zip->bzstream.avail_in = (uint32_t)in_bytes; + zip->bzstream.avail_in = (uint32_t)bytes_avail; zip->bzstream.total_in_hi32 = 0; zip->bzstream.total_in_lo32 = 0; zip->bzstream.next_out = (char*) zip->uncompressed_buffer; diff --git a/libarchive/test/test_read_format_zip_zipx_encrypted.c b/libarchive/test/test_read_format_zip_zipx_encrypted.c index ce88224a0..9badfa4da 100644 --- a/libarchive/test/test_read_format_zip_zipx_encrypted.c +++ b/libarchive/test/test_read_format_zip_zipx_encrypted.c @@ -233,6 +233,11 @@ DEFINE_TEST(test_read_format_zip_deflate_encrypted_streaming) test_encrypted_zipx("zip:compression=deflate", 1); } +DEFINE_TEST(test_read_format_zip_zipx_bzip2_encrypted_streaming) +{ + test_encrypted_zipx("zip:compression=bzip2", 1); +} + DEFINE_TEST(test_read_format_zip_zipx_zstd_encrypted_streaming) { test_encrypted_zipx("zip:compression=zstd", 1);