From fc5b6e4ddaf338780d567a9ff2cc1eb619a55e7c Mon Sep 17 00:00:00 2001 From: Nicolas Ramz Date: Fri, 5 Jan 2024 17:09:29 +0100 Subject: [PATCH] LiGfx/ILBMLoader: Don't throw if malformed bitplane can be decoded Some apps seem to generate malformed images that are accepted by most readers. We now only throw if malformed data would lead to a write outside the chunky buffer. --- Tests/LibGfx/TestImageDecoder.cpp | 11 +++++++++++ .../test-inputs/ilbm/brush-transparent-color.iff | Bin 0 -> 4858 bytes .../Libraries/LibGfx/ImageFormats/ILBMLoader.cpp | 8 +++++++- 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 Tests/LibGfx/test-inputs/ilbm/brush-transparent-color.iff diff --git a/Tests/LibGfx/TestImageDecoder.cpp b/Tests/LibGfx/TestImageDecoder.cpp index f9f7022d1ae..ffd47e6a3e6 100644 --- a/Tests/LibGfx/TestImageDecoder.cpp +++ b/Tests/LibGfx/TestImageDecoder.cpp @@ -243,6 +243,17 @@ TEST_CASE(test_24bit) EXPECT_EQ(frame.image->get_pixel(158, 270), Gfx::Color(0xee, 0x3d, 0x3c, 255)); } +TEST_CASE(test_brush_transparent_color) +{ + auto file = MUST(Core::MappedFile::map(TEST_INPUT("ilbm/brush-transparent-color.iff"sv))); + EXPECT(Gfx::ILBMImageDecoderPlugin::sniff(file->bytes())); + auto plugin_decoder = TRY_OR_FAIL(Gfx::ILBMImageDecoderPlugin::create(file->bytes())); + + auto frame = TRY_OR_FAIL(expect_single_frame_of_size(*plugin_decoder, { 266, 309 })); + + EXPECT_EQ(frame.image->get_pixel(114, 103), Gfx::Color::NamedColor::Black); +} + TEST_CASE(test_ilbm_malformed_header) { Array test_inputs = { diff --git a/Tests/LibGfx/test-inputs/ilbm/brush-transparent-color.iff b/Tests/LibGfx/test-inputs/ilbm/brush-transparent-color.iff new file mode 100644 index 0000000000000000000000000000000000000000..ed5e7268f60a30bcce54d8bacb8af38027d40d7d GIT binary patch literal 4858 zcmb`L&uSb;5XP%#1Pi%L2*DU%#^ecd$t9OTvWR1durcJ2hY0wXL&%H?#=2SOJVIU} zhYaM9i@{G2JRv8`i8Q+_t!A~o)A?$;rvL1&oDhPL)ZeeGd%CBpt9tjdhmVhlKA1iD z;^64u=<`D&`cS>6KB2Ga(=<^P(XBg4rB3c0?LR`_?UyfK;-4|*`1tt8kLb5A>Fg(> zW4ix%{{S6(^o)MEw|{hhXseUG!$%M94(&U1>)_$xS9sR5*Yw|irbKt!VLVzNyVeue z`o^`s-O=hD^DQ$nWvb~g^^B6ZT?f3`*-lOCc--zBpBQ~ZyAQZ=?aa7#igq=V#j&V& zi`DcqD1hBNARHx@IfiRkri1rl zNGUroV119B_t=vjX|Xb3lN%WPD5GJQR@N|vwT1AfSeCE^%rGS!7{F#1Y%PRe153ah z!yUXfX=f2UYwdO;O;lhY9P6yGyJ8K$GPpooVPJ@^Fz*6>qY?oDSF;&T&SYki>P7}v zdplK=_3FD(!&YrHuvNQJ7g=>|r6Z)%-KdYOdbSGC)X-#QyouFR^=>mD&sTU25qSYp zN95HOIR|OH&FQ8>e2;GjeF*Fu6+$`aixr}G?0bW#-Q9-Uf}Rb9xb&mqK0hB;7(59o zUPY|py~O*B-$?KdF=rJ%&-o;K8+weDcYF@zBO_J?`h0A$LY9%8mQX%mS-CJjm2LJCR_nkYGmqU2aZaTZ;-?w~V4%$0~E$p;{uLtleP+7NODQrS}p!Z~m`m0Tsd zpJ7cldx7MLu%G8xS47T1B$L7hIf_;wl7oe45Xs&k<+Y*WVw1cAk*u$2X=n~zjZcE^ zE~J`puj-2hmS!u?8n3G}^a4bRmyka|q~L+1u$h8LO|(Sm@(L?)6HTDxX;IIsB zb~7#{xR5%Ovgd8~lN^R)SI+FcheORKHa@O^C`fq(m4(BN!==Dt&bJV*^+BS%7%nTE zQw6RF2>#>a;}GSS1LUiqhbbU#O(kGspK^`OEKJgp;&ScS1gxRdvn35A3kheHq#jbN zr2i#e09Zx1@QpV;eqLwb7@U7G1Iies5mHN&^g|+%(t>+facvUKf5(d-7)B-CkhH~a zfhVkRGBCkt285-mHsu6ocLjt!swVU3k^t($1F@;gO+-(Ttfd-Sqal5J0)HTZMMeWE zwh$+Hw<0ct%SEi`p>BO22d9*2-rm1fIV`2vW89WqUe0dAvANOBh?DVx2HA|r`cl;l)Vk}{zX zyCj)URBbaKE0oFpa!4JbTBo>-R$jqz`eL+X&(=;2g>*jlv1%h#ImMBy?MHAtkCl9G zXN5B&-v~erC&qp!AWFWaV1+2r_Unr)ge*0_eJ-njMQhtQT%0i~uaIc;*oY4 zi+_zh{2{Q5R6Q#GB&q)t!xSa38ASr|Ryxq`Tst%M*j8D8Dkdsx#wO)&#wXvlEl%kF H_YeIIB)=N* literal 0 HcmV?d00001 diff --git a/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp b/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp index 822f151b3cc..8e2cebee1d9 100644 --- a/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp +++ b/Userland/Libraries/LibGfx/ImageFormats/ILBMLoader.cpp @@ -211,13 +211,19 @@ static ErrorOr planar_to_chunky(ReadonlyBytes bitplanes, ILBMLoading for (u8 p = 0; p < planes; p++) { u8 const plane_mask = 1 << (p % 8); size_t offset_base = (pitch * planes * y) + (p * pitch); - if (offset_base + pitch > bitplanes.size() || scanline + ((pitch - 1) * 8) + 7 >= chunky.size()) + if (offset_base + pitch > bitplanes.size()) return Error::from_string_literal("Malformed bitplane data"); for (u16 i = 0; i < pitch; i++) { u8 bit = bitplanes[offset_base + i]; u8 rgb_shift = p / 8; + // Only throw an error if we would actually attempt to write + // outside of the chunky buffer. Some apps like PPaint produce + // malformed bitplane data but files are still accepted by most readers. + if (bit && scanline + ((pitch - 1) * 8) + 7 >= chunky.size()) + return Error::from_string_literal("Malformed bitplane data"); + for (u8 b = 0; b < 8; b++) { u8 mask = 1 << (7 - b); // get current plane