mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 21:27:34 +00:00
LibCompress: Only require new LZMA2 properties after dictionary reset
This commit is contained in:
parent
d9627503a9
commit
9ccb0fc1d8
2 changed files with 63 additions and 3 deletions
|
@ -9,6 +9,65 @@
|
||||||
#include <AK/MemoryStream.h>
|
#include <AK/MemoryStream.h>
|
||||||
#include <LibCompress/Xz.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:
|
// 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)
|
// 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.
|
// Test descriptions have been taken from the README file in the test files directory.
|
||||||
|
|
|
@ -39,6 +39,10 @@ ErrorOr<Bytes> Lzma2Decompressor::read_some(Bytes bytes)
|
||||||
// " - 1 denotes a dictionary reset followed by an uncompressed chunk"
|
// " - 1 denotes a dictionary reset followed by an uncompressed chunk"
|
||||||
m_dictionary.clear();
|
m_dictionary.clear();
|
||||||
m_dictionary_initialized = true;
|
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) {
|
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"
|
// - The data to be copied verbatim into the dictionary and the output"
|
||||||
u16 data_size = TRY(m_stream->read_value<BigEndian<u16>>()) + 1;
|
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_in_uncompressed_chunk = true;
|
||||||
m_current_chunk_stream = TRY(try_make<ConstrainedStream>(MaybeOwned { *m_stream }, data_size));
|
m_current_chunk_stream = TRY(try_make<ConstrainedStream>(MaybeOwned { *m_stream }, data_size));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue