From 264b9b73ac4c47e16554f0e3c7fc8f30ceebddd9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 28 Mar 2023 21:51:57 +0200 Subject: [PATCH] LibGfx/OpenType: Ignore glyphs with bogus offsets Some fonts (like the Bootstrap Icons webfont) have bogus glyph offsets in the `loca` table that point past the end of the `glyf` table. AFAICT other rasterizers simply ignore these glyphs and treat them as if they were missing. So let's do the same. This makes https://changelog.serenityos.org/ actually work! :^) --- Userland/Libraries/LibGfx/Font/OpenType/Font.cpp | 14 ++++++++++---- Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp | 4 +++- Userland/Libraries/LibGfx/Font/OpenType/Glyf.h | 12 +++++++----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp index f2d20adaf8..9195aeb3fd 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp @@ -664,9 +664,11 @@ Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y auto horizontal_metrics = m_hmtx.get_glyph_horizontal_metrics(glyph_id); auto glyph_offset = m_loca->get_glyph_offset(glyph_id); auto glyph = m_glyf->glyph(glyph_offset); + if (!glyph.has_value()) + return {}; return Gfx::ScaledGlyphMetrics { - .ascender = static_cast(glyph.ascender()) * y_scale, - .descender = static_cast(glyph.descender()) * y_scale, + .ascender = static_cast(glyph->ascender()) * y_scale, + .descender = static_cast(glyph->descender()) * y_scale, .advance_width = static_cast(horizontal_metrics.advance_width) * x_scale, .left_side_bearing = static_cast(horizontal_metrics.left_side_bearing) * x_scale, }; @@ -708,6 +710,8 @@ RefPtr Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s return nullptr; auto glyph = m_glyf->glyph(glyph_offset0); + if (!glyph.has_value()) + return nullptr; i16 ascender = 0; i16 descender = 0; @@ -720,7 +724,7 @@ RefPtr Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s descender = m_hhea.descender(); } - return glyph.rasterize(ascender, descender, x_scale, y_scale, subpixel_offset, [&](u16 glyph_id) { + return glyph->rasterize(ascender, descender, x_scale, y_scale, subpixel_offset, [&](u16 glyph_id) { if (glyph_id >= glyph_count()) { glyph_id = 0; } @@ -857,7 +861,9 @@ Optional Font::glyph_program(u32 glyph_id) const auto glyph_offset = m_loca->get_glyph_offset(glyph_id); auto glyph = m_glyf->glyph(glyph_offset); - return glyph.program(); + if (!glyph.has_value()) + return {}; + return glyph->program(); } u32 Font::glyph_id_for_code_point(u32 code_point) const diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp index 07eed2650a..9cf1bb8533 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp @@ -367,8 +367,10 @@ RefPtr Glyf::Glyph::rasterize_simple(i16 font_ascender, i16 font_de return rasterizer.accumulate(); } -Glyf::Glyph Glyf::glyph(u32 offset) const +Optional Glyf::glyph(u32 offset) const { + if (offset + sizeof(GlyphHeader) > m_slice.size()) + return {}; VERIFY(m_slice.size() >= offset + sizeof(GlyphHeader)); auto const& glyph_header = *bit_cast(m_slice.offset_pointer(offset)); i16 num_contours = glyph_header.number_of_contours; diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h index d9001f8fd8..037bbbe8cf 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h @@ -113,12 +113,14 @@ public: auto item = opt_item.value(); Gfx::AffineTransform affine_here { transform }; affine_here.multiply(item.affine); - Glyph glyph = glyph_callback(item.glyph_id); + auto glyph = glyph_callback(item.glyph_id); + if (!glyph.has_value()) + continue; - if (glyph.m_type == Type::Simple) { - glyph.rasterize_impl(rasterizer, affine_here); + if (glyph->m_type == Type::Simple) { + glyph->rasterize_impl(rasterizer, affine_here); } else { - glyph.rasterize_composite_loop(rasterizer, transform, glyph_callback); + glyph->rasterize_composite_loop(rasterizer, transform, glyph_callback); } } } @@ -152,7 +154,7 @@ public: : m_slice(slice) { } - Glyph glyph(u32 offset) const; + Optional glyph(u32 offset) const; private: // https://learn.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers