Browse Source

LibGfx/WebPLoader: Diagnose mismatch between VP8X and VP8L alpha bits

If this turns out to be too strict in practice, we can replace it with
a `dbgln("VP8X and VP8L headers disagree about alpha; ignoring VP8X");`
instead.

ALso update catdog-alert-13-alpha-used-false.webp to not trigger this.
I had manually changed the VP8L alpha flag at offset 0x2a in
da48238fbdf4158 to clear it, but I hadn't changed the VP8X flag.
This changes the byte at offset 0x14 from 0x10 (has_alpha) to 0x00
(no alpha) as well, to match.
Nico Weber 1 year ago
parent
commit
0805319d1e

BIN
Tests/LibGfx/test-inputs/webp/catdog-alert-13-alpha-used-false.webp


+ 7 - 3
Userland/Libraries/LibGfx/ImageFormats/WebPLoader.cpp

@@ -548,11 +548,15 @@ static ErrorOr<ImageData> decode_webp_animation_frame_image_data(ANMFChunk const
     return decode_webp_set_image_data(move(alpha), move(image_data));
 }
 
-static ErrorOr<NonnullRefPtr<Bitmap>> decode_webp_image_data(ImageData const& image_data)
+static ErrorOr<NonnullRefPtr<Bitmap>> decode_webp_image_data(WebPLoadingContext& context, ImageData const& image_data)
 {
     if (image_data.image_data_chunk.id() == "VP8L"sv) {
         VERIFY(!image_data.alpha_chunk.has_value());
         auto vp8l_header = TRY(decode_webp_chunk_VP8L_header(image_data.image_data_chunk.data()));
+
+        if (context.first_chunk->id() == "VP8X" && context.vp8x_header.has_alpha != vp8l_header.is_alpha_used)
+            return Error::from_string_literal("WebPImageDecoderPlugin: VP8X header alpha flag doesn't match VP8L header");
+
         return decode_webp_chunk_VP8L_contents(vp8l_header);
     }
 
@@ -602,7 +606,7 @@ static ErrorOr<ImageFrameDescriptor> decode_webp_animation_frame(WebPLoadingCont
         }
 
         auto frame_image_data = TRY(decode_webp_animation_frame_image_data(frame_description));
-        auto frame_bitmap = TRY(decode_webp_image_data(frame_image_data));
+        auto frame_bitmap = TRY(decode_webp_image_data(context, frame_image_data));
         if (static_cast<u32>(frame_bitmap->width()) != frame_description.frame_width || static_cast<u32>(frame_bitmap->height()) != frame_description.frame_height)
             return Error::from_string_literal("WebPImageDecoderPlugin: decoded frame bitmap size doesn't match frame description size");
 
@@ -714,7 +718,7 @@ ErrorOr<ImageFrameDescriptor> WebPImageDecoderPlugin::frame(size_t index, Option
         }
 
         if (m_context->state < WebPLoadingContext::State::BitmapDecoded) {
-            auto bitmap = TRY(decode_webp_image_data(m_context->image_data.value()));
+            auto bitmap = TRY(decode_webp_image_data(*m_context, m_context->image_data.value()));
 
             // Check that size in VP8X chunk matches dimensions in VP8 or VP8L chunk if both are present.
             if (m_context->first_chunk->id() == "VP8X") {