LibCompress: Move finishing the current XZ block into its own function

This commit is contained in:
Tim Schumacher 2023-04-05 16:34:06 +02:00 committed by Brian Gianforcaro
parent 0e11e7012d
commit 68984abc43
Notes: sideshowbarker 2024-07-17 03:59:29 +09:00
2 changed files with 51 additions and 44 deletions

View file

@ -252,6 +252,55 @@ ErrorOr<bool> XzDecompressor::load_next_stream()
return true;
}
ErrorOr<void> XzDecompressor::finish_current_block()
{
auto unpadded_size = m_stream->read_bytes() - m_current_block_start_offset;
// 3.3. Block Padding:
// "Block Padding MUST contain 0-3 null bytes to make the size of
// the Block a multiple of four bytes. This can be needed when
// the size of Compressed Data is not a multiple of four."
for (size_t i = 0; (unpadded_size + i) % 4 != 0; i++) {
auto padding_byte = TRY(m_stream->read_value<u8>());
// "If any of the bytes in Block Padding are not null bytes, the decoder
// MUST indicate an error."
if (padding_byte != 0)
return Error::from_string_literal("XZ block contains a non-null padding byte");
}
// 3.4. Check:
// "The type and size of the Check field depends on which bits
// are set in the Stream Flags field (see Section 2.1.1.2).
//
// The Check, when used, is calculated from the original
// uncompressed data. If the calculated Check does not match the
// stored one, the decoder MUST indicate an error. If the selected
// type of Check is not supported by the decoder, it SHOULD
// indicate a warning or error."
auto maybe_check_size = size_for_check_type(m_stream_flags->check_type);
if (!maybe_check_size.has_value())
return Error::from_string_literal("XZ stream has an unknown check type");
// TODO: Block content checks are currently unimplemented as a whole, independent of the check type.
// For now, we only make sure to remove the correct amount of bytes from the stream.
TRY(m_stream->discard(*maybe_check_size));
unpadded_size += *maybe_check_size;
if (m_current_block_expected_uncompressed_size.has_value()) {
if (*m_current_block_expected_uncompressed_size != m_current_block_uncompressed_size)
return Error::from_string_literal("Uncompressed size of XZ block does not match the expected value");
}
TRY(m_processed_blocks.try_append({
.uncompressed_size = m_current_block_uncompressed_size,
.unpadded_size = unpadded_size,
}));
return {};
}
ErrorOr<Bytes> XzDecompressor::read_some(Bytes bytes)
{
if (!m_stream_flags.has_value()) {
@ -262,50 +311,7 @@ ErrorOr<Bytes> XzDecompressor::read_some(Bytes bytes)
if (!m_current_block_stream.has_value() || (*m_current_block_stream)->is_eof()) {
if (m_current_block_stream.has_value()) {
// We have already processed a block, so we weed to clean up trailing data before the next block starts.
auto unpadded_size = m_stream->read_bytes() - m_current_block_start_offset;
// 3.3. Block Padding:
// "Block Padding MUST contain 0-3 null bytes to make the size of
// the Block a multiple of four bytes. This can be needed when
// the size of Compressed Data is not a multiple of four."
for (size_t i = 0; (unpadded_size + i) % 4 != 0; i++) {
auto padding_byte = TRY(m_stream->read_value<u8>());
// "If any of the bytes in Block Padding are not null bytes, the decoder
// MUST indicate an error."
if (padding_byte != 0)
return Error::from_string_literal("XZ block contains a non-null padding byte");
}
// 3.4. Check:
// "The type and size of the Check field depends on which bits
// are set in the Stream Flags field (see Section 2.1.1.2).
//
// The Check, when used, is calculated from the original
// uncompressed data. If the calculated Check does not match the
// stored one, the decoder MUST indicate an error. If the selected
// type of Check is not supported by the decoder, it SHOULD
// indicate a warning or error."
auto maybe_check_size = size_for_check_type(m_stream_flags->check_type);
if (!maybe_check_size.has_value())
return Error::from_string_literal("XZ stream has an unknown check type");
// TODO: Block content checks are currently unimplemented as a whole, independent of the check type.
// For now, we only make sure to remove the correct amount of bytes from the stream.
TRY(m_stream->discard(*maybe_check_size));
unpadded_size += *maybe_check_size;
if (m_current_block_expected_uncompressed_size.has_value()) {
if (*m_current_block_expected_uncompressed_size != m_current_block_uncompressed_size)
return Error::from_string_literal("Uncompressed size of XZ block does not match the expected value");
}
TRY(m_processed_blocks.try_append({
.uncompressed_size = m_current_block_uncompressed_size,
.unpadded_size = unpadded_size,
}));
TRY(finish_current_block());
}
auto start_of_current_block = m_stream->read_bytes();

View file

@ -112,6 +112,7 @@ private:
XzDecompressor(NonnullOwnPtr<CountingStream>);
ErrorOr<bool> load_next_stream();
ErrorOr<void> finish_current_block();
NonnullOwnPtr<CountingStream> m_stream;
Optional<XzStreamFlags> m_stream_flags;