diff options
author | Tim Schumacher <timschumi@gmx.de> | 2023-03-29 03:18:00 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-30 14:39:31 +0200 |
commit | 9ccb0fc1d81e1e5f9fa2ea15993e2e9abda1b6e6 (patch) | |
tree | 5bf739c8ccb88a30fb9b0f6f012925b201f42e2b | |
parent | d9627503a9d3c33824efcb8836b33d5808f53bd6 (diff) | |
download | serenity-9ccb0fc1d81e1e5f9fa2ea15993e2e9abda1b6e6.zip |
LibCompress: Only require new LZMA2 properties after dictionary reset
-rw-r--r-- | Tests/LibCompress/TestXz.cpp | 59 | ||||
-rw-r--r-- | Userland/Libraries/LibCompress/Lzma2.cpp | 7 |
2 files changed, 63 insertions, 3 deletions
diff --git a/Tests/LibCompress/TestXz.cpp b/Tests/LibCompress/TestXz.cpp index 548511a3e9..c66d31330b 100644 --- a/Tests/LibCompress/TestXz.cpp +++ b/Tests/LibCompress/TestXz.cpp @@ -9,6 +9,65 @@ #include <AK/MemoryStream.h> #include <LibCompress/Xz.h> +TEST_CASE(lzma2_compressed_without_settings_after_uncompressed) +{ + Array<u8, 72> const compressed { + // Stream Header + 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00, // Magic + 0x00, 0x00, // Stream Flags (Check: None) + 0xFF, 0x12, 0xD9, 0x41, // CRC32 + + // Block Header + 0x02, // Block Header Size [(0x02 + 1) * 4, i.e. 12 bytes] + 0x00, // Block Flags (one filter, no compressed or uncompressed size present) + // Filter 0 Flags + 0x21, // Filter ID (0x21 for LZMA2, encoded as a multibyte integer) + 0x01, // Size of Properties (0x01, encoded as a multibyte integer) + 0x00, // Filter Properties (LZMA2 encoded dictionary size byte; 0x00 = 4 KiB) + 0x00, 0x00, 0x00, // Header Padding + 0x37, 0x27, 0x97, 0xD6, // CRC32 + + // Compressed Data (LZMA2) + // LZMA chunk with dictionary reset + 0xe0, // Control Byte + 0x00, 0x00, // Low 16 bits of uncompressed size minus one (big-endian) + 0x00, 0x05, // Compressed size minus one (big-endian) + 0x31, // LZMA properties byte (lc = 1; lp = 1; pb = 1) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Uncompressed chunk without dictionary reset + 0x02, // Control Byte + 0x00, 0x00, // 16-bit data size minus one (big-endian) + 0x00, + // LZMA chunk with state reset + 0xa0, // Control Byte + 0x00, 0x00, // Low 16 bits of uncompressed size minus one (big-endian) + 0x00, 0x05, // Compressed size minus one (big-endian) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // End of LZMA2 stream + 0x00, + + // Index + 0x00, // Index Indicator + 0x01, // Number of Records (multibyte integer) + // Record 0 + 0x28, // Unpadded Size (multibyte integer) + 0x03, // Uncompressed Size (multibyte integer) + // CRC32 + 0x3B, 0x4A, 0xD2, 0xE4, + + // Stream Footer + 0x06, 0x72, 0x9E, 0x7A, // CRC32 + 0x01, 0x00, 0x00, 0x00, // Backward Size + 0x00, 0x00, // Stream Flags + 0x59, 0x5A, // Footer Magic Bytes + }; + + auto stream = MUST(try_make<FixedMemoryStream>(compressed)); + auto decompressor = MUST(Compress::XzDecompressor::create(move(stream))); + auto buffer = MUST(decompressor->read_until_eof(PAGE_SIZE)); + EXPECT_EQ("\x00\x00\x00"sv.bytes(), buffer.span()); +} + // The following tests are based on test files from the XZ utils package, which have been placed in the public domain: // https://tukaani.org/xz/xz-5.4.1.tar.xz (subdirectory /xz-5.4.1/tests/files) // Test descriptions have been taken from the README file in the test files directory. diff --git a/Userland/Libraries/LibCompress/Lzma2.cpp b/Userland/Libraries/LibCompress/Lzma2.cpp index 92aa8c7faa..912a0c8968 100644 --- a/Userland/Libraries/LibCompress/Lzma2.cpp +++ b/Userland/Libraries/LibCompress/Lzma2.cpp @@ -39,6 +39,10 @@ ErrorOr<Bytes> Lzma2Decompressor::read_some(Bytes bytes) // " - 1 denotes a dictionary reset followed by an uncompressed chunk" m_dictionary.clear(); m_dictionary_initialized = true; + + // The XZ utils test files (bad-1-lzma2-8.xz) check that the decompressor + // requires a new set of properties after a dictionary reset. + m_last_lzma_options = {}; } if (control_byte == 1 || control_byte == 2) { @@ -52,9 +56,6 @@ ErrorOr<Bytes> Lzma2Decompressor::read_some(Bytes bytes) // - The data to be copied verbatim into the dictionary and the output" u16 data_size = TRY(m_stream->read_value<BigEndian<u16>>()) + 1; - // The test files denote an LZMA chunk without its own settings following an uncompressed chunk as invalid. - m_last_lzma_options = {}; - m_in_uncompressed_chunk = true; m_current_chunk_stream = TRY(try_make<ConstrainedStream>(MaybeOwned { *m_stream }, data_size)); } |