GHSA-m2f3-cv9x-68q7: Binary resource loader: font sizing and load passes desynchronise, causing a heap out-of-bounds write with attacker-controlled content

GHSA ID

GHSA‑m2f3‑cv9x‑68q7

CVE ID

CVE‑2026‑103414

Severity

High

CVSS score

7.8 (CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H)

CWE

CWE-787

Published

2026‑10‑02

Last updated

2026‑10‑02

Affected packages

Package Vulnerable versions Patched versions

GUIX

⇐ 6.5.1.202602a

6.5.2.202603

Description

Summary

The GUIX binary resource (theme) loader sizes its arena and populates it in two separate passes that traverse the resource file with independent cursor arithmetic. Because gx_page_header_data_size is never validated against the glyph data a page actually contains, the two passes can read different page headers for the same font page, derive different glyph counts, and reserve less than the load pass writes. The excess is written past the end of the arena, with content taken verbatim from the file.

The overflowed buffer is allocated by GUIX itself, through _gx_system_memory_allocator, rather than supplied by the caller. The public API gx_binres_theme_load() takes no size parameter, so no amount of caller diligence prevents this.

Reproduces in the shipped default configuration; GX_BINARY_RESOURCE_SUPPORT is enabled by default.

Details

The two passes advance the file read cursor by independent arithmetic. _gx_binres_font_buffer_size_get() reads a page header, then skips to the next by adding gx_page_header_data_size to the read offset. _gx_binres_one_font_load() reads a page header, then calls _gx_binres_glyphs_address_get(), which consumes glyph headers individually, advancing the cursor by each glyph header’s own data size.

gx_page_header_data_size is a file-controlled value never validated against the glyph data the page actually contains. For a multi-page font the two passes therefore read page headers from different offsets, deriving different first and last glyph values and different glyph counts. The reservation and the write disagree, and the write is larger.

_gx_binres_glyphs_address_get() then writes that many GX_GLYPH records into the arena at its running index, advancing that index by the size of the records written, without comparing either against the arena size at any point. The compressed and kerning variants share this omission.

The glyph counts are additionally computed with different widths in the two passes, UINT in one and USHORT in the other. That inconsistency is worth correcting, but on its own it produces over-allocation rather than overflow, and is not the mechanism demonstrated here.

More broadly, the arena size is computed before allocation, used for the allocation and the initial clear, and then never consulted again.

The reporter demonstrated the overflow with a multi-page font whose page header data size disagrees with its glyph data, and confirmed with a negative control that a well-formed font of the same shape does not overflow. The write begins inside the glyph record loop; the reported overflow extends by one record per additional glyph header supplied, rather than being bounded at the first byte past the arena.

Impact

The written bytes are GX_GLYPH fields — advance, ascent, descent, height, leading, width, and the gx_glyph_map pointer — taken verbatim from the resource file, so the content is attacker-chosen. The overflow extends by one record per additional glyph header supplied. A corrupted gx_glyph_map is subsequently dereferenced at render time.

Reaching this requires the product to load an untrusted GUIX Studio .bin resource, from removable media or an OTA update. That is a documented deployment model but a narrower exposure than the image decoders.

No exploit was developed and no claim of code execution is made.

Affected configurations

Any build with GX_BINARY_RESOURCE_SUPPORT, which is the default, that loads a theme resource it does not control.

Every release up to and including 6.5.1.202602a is affected. Per the project security policy the fix ships in 6.5.x, with no backport to 6.4.x.

Severity

CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H, 7.8, High.

Confidentiality is high, unlike the sibling advisory GHSA-m85v-2ccm-w6gf, because the bytes written here are chosen by the attacker rather than zeroed, and they include the gx_glyph_map pointer that the renderer later dereferences.

Patches

Fixed in GUIX 6.5.2.202603, by the change for GHSA-hgcj-22cg-4hfv. Every glyph record, whether plain, compressed or kerning, is now reserved through one helper that checks the write against the arena size, and the glyph counts are computed in one width. A load pass that asks for more than the arena holds returns GX_INVALID_MEMORY_SIZE instead of writing past the end, whatever caused the passes to disagree.

That was verified rather than reasoned about: a font needing 1520 bytes loaded into a 64 byte arena overflowed before the change and is refused after it. The glyph range in that input is well formed, 0x20 to 0x7E, so it is the arena bound doing the work and not a range check rejecting the file. That is what makes the fix hold for routes to the divergence nobody has enumerated.

A downstream fork that applies only the glyph range validation from GHSA-hgcj-22cg-4hfv remains exposed to this defect. The arena bound is the part that closes it.

Workarounds

Load binary resource files only from a trusted source. There is no build option that disables the theme loader while leaving the rest of the binary resource API usable.

Credits

Reported by Fatullayev Asadbek. Fixed by Frédéric Desbiens.

The fix was produced with AI assistance under human review, in accordance with the Eclipse Foundation’s Generative AI Usage Guidelines.