From 1d8ab74cbf960eb9888d342b5f97f5c9a3e1d267 Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Tue, 16 Mar 2021 17:39:50 +0200 Subject: [PATCH] LibCompress: Allow partial header reads in GzipDecompressor We now read the header into a temporary header byte array that is used as the header once its filled up by the input stream, instead of just ending the stream if we are out of bytes mid header. --- Userland/Libraries/LibCompress/Gzip.cpp | 12 +++++++++--- Userland/Libraries/LibCompress/Gzip.h | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibCompress/Gzip.cpp b/Userland/Libraries/LibCompress/Gzip.cpp index 8feb409cf1..5035245d09 100644 --- a/Userland/Libraries/LibCompress/Gzip.cpp +++ b/Userland/Libraries/LibCompress/Gzip.cpp @@ -106,14 +106,20 @@ size_t GzipDecompressor::read(Bytes bytes) return nread; } else { - BlockHeader header; - m_input_stream >> Bytes { &header, sizeof(header) }; + m_partial_header_offset += m_input_stream.read(Bytes { m_partial_header, sizeof(BlockHeader) }.slice(m_partial_header_offset)); - if (m_input_stream.handle_any_error()) { + if (m_input_stream.handle_any_error() || m_input_stream.unreliable_eof()) { m_eof = true; return 0; } + if (m_partial_header_offset < sizeof(BlockHeader)) { + return 0; // partial header read + } + m_partial_header_offset = 0; + + BlockHeader header = *(reinterpret_cast(m_partial_header)); + if (!header.valid_magic_number() || !header.supported_by_implementation()) { set_fatal_error(); return 0; diff --git a/Userland/Libraries/LibCompress/Gzip.h b/Userland/Libraries/LibCompress/Gzip.h index 0b7d21068a..921a2fb7b6 100644 --- a/Userland/Libraries/LibCompress/Gzip.h +++ b/Userland/Libraries/LibCompress/Gzip.h @@ -91,6 +91,8 @@ private: Member& current_member() { return m_current_member.value(); } InputStream& m_input_stream; + u8 m_partial_header[sizeof(BlockHeader)]; + size_t m_partial_header_offset { 0 }; Optional m_current_member; bool m_eof { false };