summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibCompress/Xz.cpp94
-rw-r--r--Userland/Libraries/LibCompress/Xz.h1
2 files changed, 51 insertions, 44 deletions
diff --git a/Userland/Libraries/LibCompress/Xz.cpp b/Userland/Libraries/LibCompress/Xz.cpp
index 29be32a233..b0a00c340e 100644
--- a/Userland/Libraries/LibCompress/Xz.cpp
+++ b/Userland/Libraries/LibCompress/Xz.cpp
@@ -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();
diff --git a/Userland/Libraries/LibCompress/Xz.h b/Userland/Libraries/LibCompress/Xz.h
index 5aad991cba..f9bc9b9a0a 100644
--- a/Userland/Libraries/LibCompress/Xz.h
+++ b/Userland/Libraries/LibCompress/Xz.h
@@ -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;