From 6d388249851e7180b5f9f1f61753c50515626b57 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 4 Apr 2023 11:04:54 -0400 Subject: LibCompress: Tolerate more than 288 entries in CanonicalCode Webp lossless can have up to 2328 symbols. This code assumed the deflate max of 288, leading to crashes for webp lossless files using more than 288 symbols (such as Tests/LibGfx/test-inputs/simple-vp8l.webp). Nothing writes webp files at this point, so the m_bit_codes and m_bit_code_lengths arrays aren't ever used in practice with more than 288 entries. --- Userland/Libraries/LibCompress/Deflate.cpp | 12 +++++++++++- Userland/Libraries/LibCompress/Deflate.h | 6 ++++-- 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'Userland') diff --git a/Userland/Libraries/LibCompress/Deflate.cpp b/Userland/Libraries/LibCompress/Deflate.cpp index 4f9587229a..30aa1bc68b 100644 --- a/Userland/Libraries/LibCompress/Deflate.cpp +++ b/Userland/Libraries/LibCompress/Deflate.cpp @@ -69,6 +69,10 @@ ErrorOr CanonicalCode::from_bytes(ReadonlyBytes bytes) code.m_prefix_table[1] = code.m_prefix_table[0]; code.m_max_prefixed_code_length = 1; + if (code.m_bit_codes.size() < static_cast(last_non_zero + 1)) { + TRY(code.m_bit_codes.try_resize(last_non_zero + 1)); + TRY(code.m_bit_code_lengths.try_resize(last_non_zero + 1)); + } code.m_bit_codes[last_non_zero] = 0; code.m_bit_code_lengths[last_non_zero] = 1; @@ -107,6 +111,10 @@ ErrorOr CanonicalCode::from_bytes(ReadonlyBytes bytes) code.m_symbol_values.append(symbol); } + if (code.m_bit_codes.size() < symbol + 1) { + TRY(code.m_bit_codes.try_resize(symbol + 1)); + TRY(code.m_bit_code_lengths.try_resize(symbol + 1)); + } code.m_bit_codes[symbol] = fast_reverse16(start_bit | next_code, code_length); // DEFLATE writes huffman encoded symbols as lsb-first code.m_bit_code_lengths[symbol] = code_length; @@ -159,7 +167,9 @@ ErrorOr CanonicalCode::read_symbol(LittleEndianInputBitStream& stream) cons ErrorOr CanonicalCode::write_symbol(LittleEndianOutputBitStream& stream, u32 symbol) const { - TRY(stream.write_bits(m_bit_codes[symbol], m_bit_code_lengths[symbol])); + auto code = symbol < m_bit_codes.size() ? m_bit_codes[symbol] : 0u; + auto length = symbol < m_bit_code_lengths.size() ? m_bit_code_lengths[symbol] : 0u; + TRY(stream.write_bits(code, length)); return {}; } diff --git a/Userland/Libraries/LibCompress/Deflate.h b/Userland/Libraries/LibCompress/Deflate.h index b4ab4b9c0c..f1fb086ca2 100644 --- a/Userland/Libraries/LibCompress/Deflate.h +++ b/Userland/Libraries/LibCompress/Deflate.h @@ -45,8 +45,10 @@ private: size_t m_max_prefixed_code_length { 0 }; // Compression - indexed by symbol - Array m_bit_codes {}; // deflate uses a maximum of 288 symbols (maximum of 32 for distances) - Array m_bit_code_lengths {}; + // Deflate uses a maximum of 288 symbols (maximum of 32 for distances), + // but this is also used by webp, which can use up to 256 + 24 + (1 << 11) == 2328 symbols. + Vector m_bit_codes {}; + Vector m_bit_code_lengths {}; }; class DeflateDecompressor final : public Stream { -- cgit v1.2.3