From 48ca895f5f80b58330636562e0ad9123a818475e Mon Sep 17 00:00:00 2001 From: aplefull Date: Tue, 6 May 2025 01:58:09 +0200 Subject: [PATCH] LibGfx: Properly skip color masks in BMP V2+ headers Color masks should only be used when the compression type is either BITFIELDS or ALPHABITFIELDS. They were always read before and produced corrupted images when there was random data in the mask fields. --- Libraries/LibGfx/ImageFormats/BMPLoader.cpp | 5 +++++ Tests/LibGfx/TestImageDecoder.cpp | 10 ++++++++++ Tests/LibGfx/test-inputs/bmp/2x2x32_v4.bmp | Bin 0 -> 138 bytes 3 files changed, 15 insertions(+) create mode 100644 Tests/LibGfx/test-inputs/bmp/2x2x32_v4.bmp diff --git a/Libraries/LibGfx/ImageFormats/BMPLoader.cpp b/Libraries/LibGfx/ImageFormats/BMPLoader.cpp index 3b755f406c2..ca4545d1f97 100644 --- a/Libraries/LibGfx/ImageFormats/BMPLoader.cpp +++ b/Libraries/LibGfx/ImageFormats/BMPLoader.cpp @@ -724,6 +724,11 @@ static bool decode_bmp_v2_dib(BMPLoadingContext& context, InputStreamer& streame if (!decode_bmp_info_dib(context, streamer)) return false; + if (context.dib.info.compression != Compression::BITFIELDS && context.dib.info.compression != Compression::ALPHABITFIELDS) { + streamer.drop_bytes(12); + return true; + } + context.dib.info.masks.append(streamer.read_u32()); context.dib.info.masks.append(streamer.read_u32()); context.dib.info.masks.append(streamer.read_u32()); diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index e3ee514971c..7c31a86cc29 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -84,6 +84,16 @@ TEST_CASE(test_bmp_too_many_palette_colors) TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 2, 2 })); } +TEST_CASE(test_bmp_v4) +{ + auto file = TRY_OR_FAIL(Core::MappedFile::map(TEST_INPUT("bmp/2x2x32_v4.bmp"sv))); + EXPECT(Gfx::BMPImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::BMPImageDecoderPlugin::create(file->bytes())); + + auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 2, 2 })); + EXPECT_EQ(frame.image->get_pixel(0, 0), Gfx::Color::NamedColor::Red); +} + TEST_CASE(test_ico_malformed_frame) { Array test_inputs = { diff --git a/Tests/LibGfx/test-inputs/bmp/2x2x32_v4.bmp b/Tests/LibGfx/test-inputs/bmp/2x2x32_v4.bmp new file mode 100644 index 0000000000000000000000000000000000000000..16e7d598d3050166f1ae6a11d433f32a5f168b9f GIT binary patch literal 138 zcmZ?r?P7p{Dj<~u#7t1k$e;jZF)#=K@ew`<1`7ZQC-