From c1d7a51391839e77fce4b466026353acae74ba02 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Thu, 12 Oct 2023 22:30:19 +0100 Subject: [PATCH] LibGfx/ICC: Avoid buffer overrun when creating `TextDescriptionTagData` We now validate that the offsets used cannot overflow, preventing possible buffer overruns. --- Tests/LibGfx/TestICCProfile.cpp | 1 + .../test-inputs/icc/oss-fuzz-testcase-57426.icc | Bin 0 -> 512 bytes Userland/Libraries/LibGfx/ICC/TagTypes.cpp | 13 ++++++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 Tests/LibGfx/test-inputs/icc/oss-fuzz-testcase-57426.icc diff --git a/Tests/LibGfx/TestICCProfile.cpp b/Tests/LibGfx/TestICCProfile.cpp index e3f3114508..1f420d7b48 100644 --- a/Tests/LibGfx/TestICCProfile.cpp +++ b/Tests/LibGfx/TestICCProfile.cpp @@ -262,6 +262,7 @@ TEST_CASE(to_lab) TEST_CASE(malformed_profile) { Array test_inputs = { + TEST_INPUT("icc/oss-fuzz-testcase-57426.icc"sv), TEST_INPUT("icc/oss-fuzz-testcase-59551.icc"sv), TEST_INPUT("icc/oss-fuzz-testcase-60281.icc"sv) }; diff --git a/Tests/LibGfx/test-inputs/icc/oss-fuzz-testcase-57426.icc b/Tests/LibGfx/test-inputs/icc/oss-fuzz-testcase-57426.icc new file mode 100644 index 0000000000000000000000000000000000000000..77bcb8922b1ba25321e7516086e06849963df35a GIT binary patch literal 512 zcmZQzU}8`J0|thi%)D%4XP+P^AXZRdU<5)|1_cI%#N^_F;84GC1%>|*rBIRq0vH(> zzFh;WX1J^ml7fm8O9?>r0QE6~nE!zqVQerB%r1APWk-T-tS2w*h`s~|)> TextDescriptionTagData::from_byte return Error::from_string_literal("ICC::Profile: textDescriptionType has not enough data for ASCII size"); u32 ascii_description_length = *bit_cast const*>(bytes.data() + 8); - if (bytes.size() < 3 * sizeof(u32) + ascii_description_length) + Checked ascii_description_end = 3 * sizeof(u32); + ascii_description_end += ascii_description_length; + if (ascii_description_end.has_overflow() || bytes.size() < ascii_description_end.value()) return Error::from_string_literal("ICC::Profile: textDescriptionType has not enough data for ASCII description"); u8 const* ascii_description_data = bytes.data() + 3 * sizeof(u32); @@ -1073,7 +1075,9 @@ ErrorOr> TextDescriptionTagData::from_byte // Unicode - if (bytes.size() < 3 * sizeof(u32) + ascii_description_length + 2 * sizeof(u32)) + Checked unicode_metadata_end = ascii_description_end; + unicode_metadata_end += 2 * sizeof(u32); + if (unicode_metadata_end.has_overflow() || bytes.size() < unicode_metadata_end.value()) return Error::from_string_literal("ICC::Profile: textDescriptionType has not enough data for Unicode metadata"); // "Because the Unicode language code and Unicode count immediately follow the ASCII description, @@ -1088,7 +1092,10 @@ ErrorOr> TextDescriptionTagData::from_byte u32 unicode_description_length = (u32)(cursor[0] << 24) | (u32)(cursor[1] << 16) | (u32)(cursor[2] << 8) | (u32)cursor[3]; cursor += 4; - if (bytes.size() < 3 * sizeof(u32) + ascii_description_length + 2 * sizeof(u32) + 2 * unicode_description_length) + Checked unicode_desciption_end = unicode_description_length; + unicode_desciption_end *= 2; + unicode_desciption_end += unicode_metadata_end; + if (unicode_desciption_end.has_overflow() || bytes.size() < unicode_desciption_end.value()) return Error::from_string_literal("ICC::Profile: textDescriptionType has not enough data for Unicode description"); u8 const* unicode_description_data = cursor;