|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
sfnt table-directory bounds validator run before stbtt_InitFont(). More...
Go to the source code of this file.
Enumerations | |
| enum | sfnt_layout_t : uint8_t { k_sfnt_offset_table_bytes = 12U , k_sfnt_num_tables_off = 4U , k_sfnt_table_record_bytes = 16U , k_sfnt_record_tag_off = 0U , k_sfnt_record_offset_off = 8U , k_sfnt_record_length_off = 12U } |
| Byte offsets and sizes of the sfnt offset table and table records. More... | |
| enum | sfnt_tag_t : uint32_t { k_sfnt_tag_cmap = 0x636D6170U , k_sfnt_tag_head = 0x68656164U , k_sfnt_tag_maxp = 0x6D617870U } |
| Big-endian sfnt table tags whose internal layout stbtt_InitFont() reads with an attacker-controlled count or a fixed offset. More... | |
| enum | sfnt_internal_layout_t : uint8_t { k_cmap_header_bytes = 4U , k_cmap_num_tables_off = 2U , k_cmap_record_bytes = 8U , k_head_loc_format_end = 52U , k_maxp_num_glyphs_end = 6U } |
| Byte offsets stbtt_InitFont() reads inside cmap / head / maxp. More... | |
| enum | sfnt_shift_t : uint8_t { k_sfnt_shift_8 = 8U , k_sfnt_shift_16 = 16U , k_sfnt_shift_24 = 24U } |
| Bit-shift distances for assembling big-endian scalars. More... | |
Functions | |
| static uint16_t | internal_rd_be_u16 (const uint8_t *p) |
| Read a big-endian uint16 from a two-byte, in-bounds location. | |
| static uint32_t | internal_rd_be_u32 (const uint8_t *p) |
| Read a big-endian uint32 from a four-byte, in-bounds location. | |
| static bool | internal_table_internal_in_bounds (const uint8_t *data, uint64_t buf_len, uint32_t tag, uint64_t t_off) |
| Prove the reads stbtt_InitFont() makes inside a known table stay in-bounds, given the table's already-validated file offset. | |
| bool | ra8_stbtt_sfnt_dir_in_bounds (const uint8_t *data, size_t len, uint32_t fontstart) |
| Verify that a font's sfnt table directory lies within its buffer. | |
sfnt table-directory bounds validator run before stbtt_InitFont().
See ra8_stbtt_guard.h for the threat model. This translation unit is a pure, heap-free big-endian sfnt parser: it reads only the offset table and the table directory, proving every access stays inside the caller-supplied buffer, and returns a verdict without ever calling into stb_truetype.
[Ring 4 / Reflow] {World: NS}
Definition in file ra8_stbtt_guard.c.
| enum sfnt_internal_layout_t : uint8_t |
Byte offsets stbtt_InitFont() reads inside cmap / head / maxp.
The top-level directory guard proves each table's declared [offset, offset + length) fits, but stbtt_InitFont_internal() then reads fields inside those tables using values it trusts from the table itself – most dangerously the cmap encoding-record count, which it multiplies by 8 to stride the sub-directory with no length check. These constants name the exact extents those reads require.
Definition at line 72 of file ra8_stbtt_guard.c.
| enum sfnt_layout_t : uint8_t |
Byte offsets and sizes of the sfnt offset table and table records.
All values are fixed by the OpenType/TrueType sfnt container format and are big-endian on disk. Named here so the parser carries no bare structural literals.
Definition at line 36 of file ra8_stbtt_guard.c.
| enum sfnt_shift_t : uint8_t |
Bit-shift distances for assembling big-endian scalars.
Named to keep the byte-swap helpers free of magic shift counts.
| Enumerator | |
|---|---|
| k_sfnt_shift_8 | One-byte shift. |
| k_sfnt_shift_16 | Two-byte shift. |
| k_sfnt_shift_24 | Three-byte shift. |
Definition at line 86 of file ra8_stbtt_guard.c.
| enum sfnt_tag_t : uint32_t |
Big-endian sfnt table tags whose internal layout stbtt_InitFont() reads with an attacker-controlled count or a fixed offset.
Each value is the four ASCII tag bytes assembled most-significant first, i.e. exactly what internal_rd_be_u32 returns for the record's tag field.
| Enumerator | |
|---|---|
| k_sfnt_tag_cmap | 'cmap' – character-to-glyph mapping. |
| k_sfnt_tag_head | 'head' – font header (indexToLocFormat). |
| k_sfnt_tag_maxp | 'maxp' – maximum profile (numGlyphs). |
Definition at line 55 of file ra8_stbtt_guard.c.
|
static |
Read a big-endian uint16 from a two-byte, in-bounds location.
Assembles p[0] (most-significant) and p[1] into a host-order 16-bit value via a shift-and-or. Pure computation on two bytes the caller has already proven readable and in-bounds; performs no bound check itself.
| [in] | p | Pointer to the first (most-significant) byte to read. |
| 0 | Both source bytes were zero. |
p is non-null and points at two readable bytes proven in-bounds by the caller. Definition at line 111 of file ra8_stbtt_guard.c.
References k_sfnt_shift_8.
Referenced by internal_table_internal_in_bounds(), and ra8_stbtt_sfnt_dir_in_bounds().
|
static |
Read a big-endian uint32 from a four-byte, in-bounds location.
Assembles p[0..3] most-significant-byte-first into a host-order 32-bit value via shift-and-or. Pure computation on four bytes the caller has already proven readable and in-bounds; performs no bound check itself.
| [in] | p | Pointer to the first (most-significant) byte to read. |
| 0 | All four source bytes were zero. |
p is non-null and points at four readable bytes proven in-bounds by the caller. Definition at line 135 of file ra8_stbtt_guard.c.
References k_sfnt_shift_16, k_sfnt_shift_24, and k_sfnt_shift_8.
Referenced by ra8_stbtt_sfnt_dir_in_bounds().
|
static |
Prove the reads stbtt_InitFont() makes inside a known table stay in-bounds, given the table's already-validated file offset.
The top-level directory guard only proves each table's declared extent fits. stbtt_InitFont_internal() then reads fields inside three tables using values it trusts from the table's own bytes – none of which the declared length constrains:
| [in] | data | First byte of the font buffer (caller-proven non-null). |
| [in] | buf_len | Buffer length in bytes. |
| [in] | tag | Big-endian 4-byte table tag (see sfnt_tag_t). |
| [in] | t_off | Table file offset, already proven < buf_len by the per-record extent check in the caller. |
| true | Table-internal reads are in-bounds, or tag is not cmap/head/maxp. |
| false | A cmap/head/maxp internal read would escape [data, data+len). |
data references at least buf_len readable bytes. t_off is < buf_len (the record's declared offset fits). data and its buffer are unmodified (pure read). Definition at line 180 of file ra8_stbtt_guard.c.
References internal_rd_be_u16(), k_cmap_header_bytes, k_cmap_num_tables_off, k_cmap_record_bytes, k_head_loc_format_end, k_maxp_num_glyphs_end, k_sfnt_tag_cmap, k_sfnt_tag_head, and k_sfnt_tag_maxp.
Referenced by ra8_stbtt_sfnt_dir_in_bounds().
| bool ra8_stbtt_sfnt_dir_in_bounds | ( | const uint8_t * | data, |
| size_t | len, | ||
| uint32_t | fontstart ) |
Verify that a font's sfnt table directory lies within its buffer.
Mirrors exactly the reads stbtt_InitFont() / stbtt__find_table() make while walking the sfnt offset table, table directory, and the table-internal fields InitFont reads, and confirms each one stays inside [0, len):
All arithmetic is performed in uint64_t so that a hostile fontstart (up to UINT32_MAX, e.g. a crafted TrueType-collection sub-font offset) or a hostile per-table offset/length cannot overflow the bound computation. The function bounds every read stbtt_InitFont() itself issues. It does NOT bound the deeper reads the glyph-lookup / rasterisation path makes after init (stbtt_FindGlyphIndex following an attacker-controlled cmap subtable offset, then the loca / glyf outline walk); stb_truetype does not bound those against the buffer either, so a crafted font can still drive an out-of-bounds read there. Hardening that deeper path is tracked separately as parser hardening (issue #179); it is a much larger change than this directory pre-check.
| [in] | data | Pointer to the first byte of the font buffer. |
| [in] | len | Length of the font buffer, bytes. |
| [in] | fontstart | Byte offset of this font's sfnt offset table within data (0 for a bare TTF/OTF; the sub-font offset for a TrueType collection). This is the same value passed as the offset argument to stbtt_InitFont(). |
| true | The directory is in bounds; stbtt_InitFont() may safely walk it. |
| false | data is nullptr, or the offset table / directory / any table record / a cmap-head-maxp internal read extends past len – reject the font. |
data references at least len readable bytes (or is nullptr). len is the true byte length of the buffer data points to. data and the buffer it points to are unmodified (pure read). Definition at line 204 of file ra8_stbtt_guard.c.
References internal_rd_be_u16(), internal_rd_be_u32(), internal_table_internal_in_bounds(), k_sfnt_num_tables_off, k_sfnt_offset_table_bytes, k_sfnt_record_length_off, k_sfnt_record_offset_off, k_sfnt_record_tag_off, and k_sfnt_table_record_bytes.
Referenced by internal_font_init(), reflow_bind_font(), and reflow_register_face().