From 1a6da4fbf23c98805f7e8df55658e5a24e3145e1 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Wed, 1 Nov 2023 16:13:06 +0000 Subject: [PATCH] LibGfx: Mark OpenType file data structs as packed, and assert sizes Some of these are odd sizes. We managed not to insert padding because BigEndian is itself marked as packed, but let's be explicit instead of relying on that. :^) --- .../Libraries/LibGfx/Font/OpenType/Glyf.h | 3 +- .../Libraries/LibGfx/Font/OpenType/Tables.h | 120 ++++++++++++------ 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h index 5901686c55..c70c947327 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Glyf.h @@ -174,13 +174,14 @@ public: private: // https://learn.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers - struct GlyphHeader { + struct [[gnu::packed]] GlyphHeader { BigEndian number_of_contours; BigEndian x_min; BigEndian y_min; BigEndian x_max; BigEndian y_max; }; + static_assert(AssertSize()); ReadonlyBytes m_slice; }; diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h index 877fd0d287..b921867653 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h @@ -24,19 +24,22 @@ enum class IndexToLocFormat { Offset32, }; -struct Fixed { +struct [[gnu::packed]] Fixed { BigEndian integer; BigEndian fraction; }; +static_assert(AssertSize()); -struct LongDateTime { +struct [[gnu::packed]] LongDateTime { BigEndian value; }; +static_assert(AssertSize()); -struct Version16Dot16 { +struct [[gnu::packed]] Version16Dot16 { BigEndian major; BigEndian minor; }; +static_assert(AssertSize()); using FWord = BigEndian; using UFWord = BigEndian; @@ -79,7 +82,7 @@ public: IndexToLocFormat index_to_loc_format() const; private: - struct FontHeaderTable { + struct [[gnu::packed]] FontHeaderTable { BigEndian major_version; BigEndian minor_version; Fixed font_revision; @@ -99,6 +102,7 @@ private: BigEndian index_to_loc_format; BigEndian glyph_data_format; }; + static_assert(AssertSize()); FontHeaderTable const& header() const { return *bit_cast(m_slice.data()); } @@ -122,7 +126,7 @@ public: u16 number_of_h_metrics() const; private: - struct HorizontalHeaderTable { + struct [[gnu::packed]] HorizontalHeaderTable { BigEndian major_version; BigEndian minor_version; FWord ascender; @@ -139,6 +143,7 @@ private: BigEndian metric_data_format; BigEndian number_of_h_metrics; }; + static_assert(AssertSize()); HorizontalHeaderTable const& header() const { return *bit_cast(m_slice.data()); } @@ -159,12 +164,13 @@ public: u16 num_glyphs() const; private: - struct MaximumProfileVersion0_5 { + struct [[gnu::packed]] MaximumProfileVersion0_5 { Version16Dot16 version; BigEndian num_glyphs; }; + static_assert(AssertSize()); - struct MaximumProfileVersion1_0 { + struct [[gnu::packed]] MaximumProfileVersion1_0 { Version16Dot16 version; BigEndian num_glyphs; BigEndian max_points; @@ -181,6 +187,7 @@ private: BigEndian max_component_elements; BigEndian max_component_depths; }; + static_assert(AssertSize()); MaximumProfileVersion0_5 const& header() const { return *bit_cast(m_slice.data()); } @@ -235,10 +242,11 @@ public: GlyphHorizontalMetrics get_glyph_horizontal_metrics(u32 glyph_id) const; private: - struct LongHorMetric { + struct [[gnu::packed]] LongHorMetric { BigEndian advance_width; BigEndian lsb; }; + static_assert(AssertSize()); Hmtx(ReadonlyBytes slice, u32 num_glyphs, u32 number_of_h_metrics) : m_slice(slice) @@ -273,7 +281,7 @@ public: } private: - struct Version0 { + struct [[gnu::packed]] Version0 { BigEndian version; BigEndian avg_char_width; BigEndian us_weight_class; @@ -305,14 +313,16 @@ private: BigEndian us_win_ascent; BigEndian us_win_descent; }; + static_assert(AssertSize()); - struct Version1 { + struct [[gnu::packed]] Version1 { Version0 version0; BigEndian ul_code_page_range1; BigEndian ul_code_page_range2; }; + static_assert(AssertSize()); - struct Version2 { + struct [[gnu::packed]] Version2 { Version1 version1; BigEndian sx_height; BigEndian s_cap_height; @@ -320,6 +330,7 @@ private: BigEndian us_break_char; BigEndian us_max_context; }; + static_assert(AssertSize()); Version0 const& header() const { return *bit_cast(m_slice.data()); } Version2 const& header_v2() const @@ -355,7 +366,7 @@ public: private: // https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-records - struct NameRecord { + struct [[gnu::packed]] NameRecord { BigEndian platform_id; BigEndian encoding_id; BigEndian language_id; @@ -363,14 +374,16 @@ private: BigEndian length; Offset16 string_offset; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-0 - struct NamingTableVersion0 { + struct [[gnu::packed]] NamingTableVersion0 { BigEndian version; BigEndian count; Offset16 storage_offset; NameRecord name_record[0]; }; + static_assert(AssertSize()); NamingTableVersion0 const& header() const { return *bit_cast(m_slice.data()); } @@ -408,30 +421,34 @@ public: i16 get_glyph_kerning(u16 left_glyph_id, u16 right_glyph_id) const; private: - struct Header { + struct [[gnu::packed]] Header { BigEndian version; BigEndian n_tables; }; + static_assert(AssertSize()); - struct SubtableHeader { + struct [[gnu::packed]] SubtableHeader { BigEndian version; BigEndian length; BigEndian coverage; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/kern#format-0 - struct Format0 { + struct [[gnu::packed]] Format0 { BigEndian n_pairs; BigEndian search_range; BigEndian entry_selector; BigEndian range_shift; }; + static_assert(AssertSize()); - struct Format0Pair { + struct [[gnu::packed]] Format0Pair { BigEndian left; BigEndian right; FWord value; }; + static_assert(AssertSize()); Header const& header() const { return *bit_cast
(m_slice.data()); } @@ -452,7 +469,7 @@ private: class EBLC { public: // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record - struct SbitLineMetrics { + struct [[gnu::packed]] SbitLineMetrics { i8 ascender {}; i8 descender {}; u8 width_max {}; @@ -466,27 +483,31 @@ public: i8 pad1 {}; i8 pad2 {}; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray - struct IndexSubTableArray { + struct [[gnu::packed]] IndexSubTableArray { BigEndian first_glyph_index; BigEndian last_glyph_index; Offset32 additional_offset_to_index_subtable; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubheader - struct IndexSubHeader { + struct [[gnu::packed]] IndexSubHeader { BigEndian index_format; BigEndian image_format; Offset32 image_data_offset; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets // IndexSubTable1: variable-metrics glyphs with 4-byte offsets - struct IndexSubTable1 { + struct [[gnu::packed]] IndexSubTable1 { IndexSubHeader header; Offset32 sbit_offsets[]; }; + static_assert(AssertSize()); }; // https://learn.microsoft.com/en-us/typography/opentype/spec/cblc @@ -494,7 +515,7 @@ public: class CBLC { public: // https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#bitmapsize-record - struct BitmapSize { + struct [[gnu::packed]] BitmapSize { Offset32 index_subtable_array_offset; BigEndian index_tables_size; BigEndian number_of_index_subtables; @@ -508,14 +529,16 @@ public: u8 bit_depth {}; i8 flags {}; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#cblcheader - struct CblcHeader { + struct [[gnu::packed]] CblcHeader { BigEndian major_version; BigEndian minor_version; BigEndian num_sizes; BitmapSize bitmap_sizes[]; }; + static_assert(AssertSize()); CblcHeader const& header() const { return *bit_cast(m_slice.data()); } ReadonlySpan bitmap_sizes() const { return { header().bitmap_sizes, header().num_sizes }; } @@ -540,13 +563,14 @@ private: class EBDT { public: // https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#smallglyphmetrics - struct SmallGlyphMetrics { + struct [[gnu::packed]] SmallGlyphMetrics { u8 height {}; u8 width {}; i8 bearing_x {}; i8 bearing_y {}; u8 advance {}; }; + static_assert(AssertSize()); }; // https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt @@ -554,17 +578,19 @@ public: class CBDT { public: // https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#table-structure - struct CbdtHeader { + struct [[gnu::packed]] CbdtHeader { BigEndian major_version; BigEndian minor_version; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#format-17-small-metrics-png-image-data - struct Format17 { + struct [[gnu::packed]] Format17 { EBDT::SmallGlyphMetrics glyph_metrics; BigEndian data_len; u8 data[]; }; + static_assert(AssertSize()); static ErrorOr from_slice(ReadonlyBytes); ReadonlyBytes bytes() const { return m_slice; } @@ -581,87 +607,98 @@ private: }; // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table -struct FeatureRecord { +struct [[gnu::packed]] FeatureRecord { Tag feature_tag; Offset16 feature_offset; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table -struct FeatureList { +struct [[gnu::packed]] FeatureList { BigEndian feature_count; FeatureRecord feature_records[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table -struct Feature { +struct [[gnu::packed]] Feature { Offset16 feature_params_offset; BigEndian lookup_index_count; BigEndian lookup_list_indices[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table -struct Lookup { +struct [[gnu::packed]] Lookup { BigEndian lookup_type; BigEndian lookup_flag; BigEndian subtable_count; Offset16 subtable_offsets[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table -struct LookupList { +struct [[gnu::packed]] LookupList { BigEndian lookup_count; Offset16 lookup_offsets[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1 -struct CoverageFormat1 { +struct [[gnu::packed]] CoverageFormat1 { BigEndian coverage_format; BigEndian glyph_count; BigEndian glyph_array[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2 -struct RangeRecord { +struct [[gnu::packed]] RangeRecord { BigEndian start_glyph_id; BigEndian end_glyph_id; BigEndian start_coverage_index; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2 -struct CoverageFormat2 { +struct [[gnu::packed]] CoverageFormat2 { BigEndian coverage_format; BigEndian range_count; RangeRecord range_records[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2 -struct ClassRangeRecord { +struct [[gnu::packed]] ClassRangeRecord { BigEndian start_glyph_id; BigEndian end_glyph_id; BigEndian class_; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2 -struct ClassDefFormat2 { +struct [[gnu::packed]] ClassDefFormat2 { BigEndian class_format; BigEndian class_range_count; ClassRangeRecord class_range_records[]; }; +static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header class GPOS { public: // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header - struct GPOSHeader { + struct [[gnu::packed]] GPOSHeader { BigEndian major_version; BigEndian minor_version; Offset16 script_list_offset; Offset16 feature_list_offset; Offset16 lookup_list_offset; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs - struct PairPosFormat1 { + struct [[gnu::packed]] PairPosFormat1 { BigEndian pos_format; Offset16 coverage_offset; BigEndian value_format1; @@ -669,9 +706,10 @@ public: BigEndian pair_set_count; Offset16 pair_set_offsets[]; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#value-record - struct ValueRecord { + struct [[gnu::packed]] ValueRecord { BigEndian x_placement; BigEndian y_placement; BigEndian x_advance; @@ -681,9 +719,10 @@ public: Offset16 x_advance_device_offset; Offset16 y_advance_device_offset; }; + static_assert(AssertSize()); // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment - struct PairPosFormat2 { + struct [[gnu::packed]] PairPosFormat2 { BigEndian pos_format; Offset16 coverage_offset; BigEndian value_format1; @@ -693,6 +732,7 @@ public: BigEndian class1_count; BigEndian class2_count; }; + static_assert(AssertSize()); enum class ValueFormat : u16 { X_PLACEMENT = 0x0001,