From 338d64abd9c446d405d824a02552234c756c02d7 Mon Sep 17 00:00:00 2001 From: Lucas CHOLLET Date: Sat, 29 Jul 2023 15:16:33 -0400 Subject: [PATCH] LibGfx/JPEG: Don't fail to decode images with non-compliant ICC profile Some images (like https://www.w3.org/Press/Stock/Berners-Lee/2001-europaeum-eighth.jpg) embed a non-compliant ICC profile. Instead of rejecting the image, we can simply discard the color profile and resume the decoding of the bitmap. --- .../LibGfx/ImageFormats/JPEGLoader.cpp | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp index aff847ee65..df928c4992 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp @@ -1044,21 +1044,34 @@ static ErrorOr read_icc_profile(JPEGStream& stream, JPEGLoadingContext& co context.icc_multi_chunk_state.emplace(ICCMultiChunkState { 0, TRY(FixedArray::create(number_of_chunks)) }); auto& chunk_state = context.icc_multi_chunk_state; - if (chunk_state->seen_number_of_icc_chunks >= number_of_chunks) - return Error::from_string_literal("Too many ICC chunks"); + u8 index {}; - if (chunk_state->chunks.size() != number_of_chunks) - return Error::from_string_literal("Inconsistent number of total ICC chunks"); + auto const ensure_correctness = [&]() -> ErrorOr { + if (chunk_state->seen_number_of_icc_chunks >= number_of_chunks) + return Error::from_string_literal("Too many ICC chunks"); - if (chunk_sequence_number == 0) - return Error::from_string_literal("ICC chunk sequence number not 1 based"); - u8 index = chunk_sequence_number - 1; + if (chunk_state->chunks.size() != number_of_chunks) + return Error::from_string_literal("Inconsistent number of total ICC chunks"); - if (index >= chunk_state->chunks.size()) - return Error::from_string_literal("ICC chunk sequence number larger than number of chunks"); + if (chunk_sequence_number == 0) + return Error::from_string_literal("ICC chunk sequence number not 1 based"); - if (!chunk_state->chunks[index].is_empty()) - return Error::from_string_literal("Duplicate ICC chunk at sequence number"); + index = chunk_sequence_number - 1; + + if (index >= chunk_state->chunks.size()) + return Error::from_string_literal("ICC chunk sequence number larger than number of chunks"); + + if (!chunk_state->chunks[index].is_empty()) + return Error::from_string_literal("Duplicate ICC chunk at sequence number"); + + return {}; + }; + + if (auto result = ensure_correctness(); result.is_error()) { + dbgln_if(JPEG_DEBUG, "JPEG: {}", result.release_error()); + TRY(stream.discard(bytes_to_read)); + return {}; + } chunk_state->chunks[index] = TRY(ByteBuffer::create_zeroed(bytes_to_read)); TRY(stream.read_until_filled(chunk_state->chunks[index]));