GHSA-m85v-2ccm-w6gf: Binary resource loader: unbounded map_id from a theme file causes a heap out-of-bounds write in the GUIX-allocated arena
GHSA ID |
|
|---|---|
CVE ID |
CVE‑2026‑92449 |
Severity |
High |
CVSS score |
7.3 ( |
CWE |
|
Published |
2026‑10‑02 |
Last updated |
2026‑10‑02 |
Affected packages
| Package | Vulnerable versions | Patched versions |
|---|---|---|
GUIX |
>= 6.3.0, ⇐ 6.5.1.202602a |
6.5.2.202603 |
Description
Summary
_gx_binres_pixelmap_table_load() in the GUIX binary resource (theme) loader indexes the pixelmap table with a value read verbatim from the resource file and never bounds it against the table size. A crafted theme drives a write of up to roughly 256 KB past the end of the table.
The overflowed buffer is allocated by GUIX itself, through _gx_system_memory_allocator, rather than supplied by the caller, so the loader corrupts its own arena. 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
map_id originates from the pixelmap header’s index field, while the table was sized from the unrelated theme header pixelmap count. The two are never reconciled. A resource declaring a large pixelmap index drives a while loop that fills entries with GX_NULL past the end of the table, and the store that follows then writes a pointer at that out-of-bounds index.
The number of out-of-bounds stores is selected by one field in the file. A resource declaring an index of 0xFFFF produces a write of 262136 bytes; an index of 40 produces 156 bytes, which is 39 entries of 4 bytes, confirming that the length follows that field exactly. A resource declaring an index of 1 produces no overflow.
There is a second, independent defect in the same fifteen lines. The status of _gx_binres_one_pixelmap_load() was examined only after both writes. That function assigns the pixelmap and the index only on its success paths, and both are uninitialised locals in the caller, so a failed load left the loop bound indeterminate and stored indeterminate stack data as a GX_PIXELMAP *, which is later dereferenced. Bounding the index alone does not close this; the status check has to precede both writes.
More broadly, the arena size is computed before allocation and then never consulted again. No site that writes into the arena compares its running index against it.
Impact
A controlled-length, controlled-offset write of zeros, followed by a single out-of-bounds pointer store. The length is selectable from 4 bytes to roughly 256 KB by one field in the file. This is not an arbitrary-content write. On a flat MCU heap it destroys adjacent allocator metadata and live pointers; the subsequent dereference of an indeterminate GX_PIXELMAP * is an independent failure.
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.
Introduced in 6.3.0 and present in every release since, up to and including 6.5.1.202602a. The 6.2.x releases and earlier build the table differently and are not affected.
Severity
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:H, 7.3, High.
Availability is high rather than low because a selectable zero write of up to roughly 256 KB across a flat MCU heap destroys allocator metadata as a matter of course, not merely the pointers it lands on. Confidentiality is low rather than high because the only path to disclosure is the indeterminate pointer store happening to reference readable memory whose contents then reach the display, which was not demonstrated.
Patches
Fixed in GUIX 6.5.2.202603. The status of _gx_binres_one_pixelmap_load() is examined before any store, so a failed load no longer reaches the table, and a pixelmap index that does not fit the table is rejected with GX_INVALID_FORMAT. Both locals are initialised. Enforcing the arena size at every site that writes into it is a broader change and belongs with the resource-length work, not here.
This fix ships without a dedicated regression test, which the other reports from the same reporter do carry. _gx_binres_pixelmap_table_load() is static and reachable only through gx_binres_theme_load(), and the tests that drive it compare rendered output against golden files, so a malformed theme binary is needed as a fixture. The resource format reuses one magic number across its header types, so a fixture produced by scanning and patching a valid theme cannot reliably place the pixelmap header, and a fixture rejected for the wrong reason would pass while testing nothing. A generator that places the header at a known offset is the way to close this, and is being pursued separately.