Bladeren bron

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.
Lucas CHOLLET 2 jaren geleden
bovenliggende
commit
338d64abd9
1 gewijzigde bestanden met toevoegingen van 24 en 11 verwijderingen
  1. 24 11
      Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp

+ 24 - 11
Userland/Libraries/LibGfx/ImageFormats/JPEGLoader.cpp

@@ -1044,21 +1044,34 @@ static ErrorOr<void> read_icc_profile(JPEGStream& stream, JPEGLoadingContext& co
         context.icc_multi_chunk_state.emplace(ICCMultiChunkState { 0, TRY(FixedArray<ByteBuffer>::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<void> {
+        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]));