diff --git a/Tests/LibTTF/TestCmap.cpp b/Tests/LibTTF/TestCmap.cpp index f86a722bf7..50918efaf0 100644 --- a/Tests/LibTTF/TestCmap.cpp +++ b/Tests/LibTTF/TestCmap.cpp @@ -11,7 +11,7 @@ TEST_CASE(test_cmap_format_4) { // clang-format off // Big endian. - u8 cmap_table[] = + Array const cmap_table = { // https://docs.microsoft.com/en-us/typography/opentype/spec/cmap#cmap-header 0, 0, // uint16 version @@ -54,7 +54,7 @@ TEST_CASE(test_cmap_format_4) 0, 0, }; // clang-format on - auto cmap = OpenType::Cmap::from_slice({ cmap_table, sizeof cmap_table }).value(); + auto cmap = OpenType::Cmap::from_slice(cmap_table.span()).value(); cmap.set_active_index(0); // Format 4 can't handle code points > 0xffff. @@ -78,4 +78,11 @@ TEST_CASE(test_cmap_format_4) EXPECT_EQ(cmap.glyph_id_for_code_point(0xfeff), 0u); EXPECT_EQ(cmap.glyph_id_for_code_point(0xffff), 0xffffu); EXPECT_EQ(cmap.glyph_id_for_code_point(0x1'0000), 0u); + + // Set the number of subtables to a value, where the record offset for the last subtable is greater than the + // total table size. We should not crash if a Cmap table is truncated in this way. + auto malformed_cmap_table = cmap_table; + malformed_cmap_table[3] = 13; + auto cmap_with_invalid_subtable_offset = OpenType::Cmap::from_slice(malformed_cmap_table.span()).value(); + EXPECT(!cmap_with_invalid_subtable_offset.subtable(12).has_value()); } diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Cmap.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Cmap.cpp index 88842f80d0..fff80e0600 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Cmap.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Cmap.cpp @@ -68,6 +68,8 @@ Optional Cmap::subtable(u32 index) const return {}; } u32 record_offset = (u32)Sizes::TableHeader + index * (u32)Sizes::EncodingRecord; + if (record_offset + (u32)Offsets::EncodingRecord_Offset >= m_slice.size()) + return {}; u16 platform_id = be_u16(m_slice.offset(record_offset)); u16 encoding_id = be_u16(m_slice.offset(record_offset + (u32)Offsets::EncodingRecord_EncodingID)); u32 subtable_offset = be_u32(m_slice.offset(record_offset + (u32)Offsets::EncodingRecord_Offset));