CVE-2026-50593
Description
Graphite versions prior to 1.3.15 contain an integer underflow leading to an out-of-bounds write, potentially allowing for code execution.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Graphite versions prior to 1.3.15 contain an integer underflow leading to an out-of-bounds write, potentially allowing for code execution.
Vulnerability
Graphite versions before 1.3.15 are vulnerable to an integer underflow and subsequent out-of-bounds write when processing Graphite actions. This occurs because the slotat function does not validate that an offset is within the allowed slot-map range [1].
Exploitation
An attacker can trigger this vulnerability by crafting specific Graphite actions. The vulnerability is present in the slotat macro, which can be called with an offset that causes an integer underflow. This underflow results in an out-of-bounds write when accessing the map array [2].
Impact
Successful exploitation of this vulnerability can lead to an out-of-bounds write, which may allow an attacker to corrupt memory and potentially achieve arbitrary code execution. The exact impact depends on the context in which the vulnerability is triggered and the privileges of the running Graphite process.
Mitigation
Graphite version 1.3.15, released on 2026-06-05, addresses this vulnerability by adding bounds checking to the slotat macro [1, 2]. Users are advised to update to version 1.3.15 or later. No workarounds are specified in the available references.
AI Insight generated on Jun 5, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
1ad78c6b73199Fix an underflow case that can be induced by crafted graphite actions.
5 files changed · +478 −1
src/inc/opcodes.h+2 −1 modified@@ -53,7 +53,8 @@ #define push(n) { *++sp = n; } #define pop() (*sp--) -#define slotat(x) (map[(x)]) +#define slotat(x) ((map + (x) >= &smap[-1] && map + (x) < smap.end()) ? \ + map[(x)] : (status = Machine::slot_offset_out_bounds, nullptr)) #define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); } #define POSITIONED 1
tests/CMakeLists.txt+1 −0 modified@@ -111,6 +111,7 @@ fonttest(magyar3 MagyarLinLibertineG.ttf 0066 0069 0066 0074 0079 002d 0066 0069 fonttest(grtest1 grtest1gr.ttf 0062 0061 0061 0061 0061 0061 0061 0062 0061) fonttest(general1 general.ttf 0E01 0062) fonttest(piglatin1 PigLatinBenchmark_v3.ttf 0068 0065 006C 006C 006F) +fonttest(underflow underflow.ttf 0062 0061 0061 0061 0061 0061 0061 0062) feattest(padauk_feat Padauk.ttf) feattest(charis_feat charis_r_gr.ttf)
tests/fonts/underflow.ttf+0 −0 addedtests/standards/underflow.json+473 −0 added@@ -0,0 +1,473 @@ +[ + { + "id" : "4691-00-3610", + "passes" : [ + { + "id" : 1, + "slotsdir" : "ltr", + "passdir" : "ltr", + "slots" : [ + { + "id" : "4691-01-37f0", + "gid" : 68, + "charinfo" : { "original" : 0, "before" : 0, "after" : 0 }, + "origin" : [ 0, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 520, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3870", + "gid" : 67, + "charinfo" : { "original" : 1, "before" : 1, "after" : 1 }, + "origin" : [ 520, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-38f0", + "gid" : 67, + "charinfo" : { "original" : 2, "before" : 2, "after" : 2 }, + "origin" : [ 982, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3970", + "gid" : 67, + "charinfo" : { "original" : 3, "before" : 3, "after" : 3 }, + "origin" : [ 1444, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-39f0", + "gid" : 67, + "charinfo" : { "original" : 4, "before" : 4, "after" : 4 }, + "origin" : [ 1906, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3a70", + "gid" : 67, + "charinfo" : { "original" : 5, "before" : 5, "after" : 5 }, + "origin" : [ 2368, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3af0", + "gid" : 67, + "charinfo" : { "original" : 6, "before" : 6, "after" : 6 }, + "origin" : [ 2830, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3b70", + "gid" : 68, + "charinfo" : { "original" : 7, "before" : 7, "after" : 7 }, + "origin" : [ 3292, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 520, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + } + ], + "rules" : [ + { + "considered" : [ + { "id" : 0, "failed" : false, "input" : { "start" : "4691-01-37f0", "length" : 8 } } + ], + "output" : { + "range" : { "start" : "4691-01-37f0", "end" : "0000-00-0000" }, + "slots" : [ + { + "id" : "4691-01-37f0", + "gid" : 36, + "charinfo" : { "original" : 0, "before" : 0, "after" : 0 }, + "origin" : [ 0, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 676, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3870", + "gid" : 67, + "charinfo" : { "original" : 1, "before" : 1, "after" : 1 }, + "origin" : [ 676, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-38f0", + "gid" : 67, + "charinfo" : { "original" : 2, "before" : 2, "after" : 2 }, + "origin" : [ 1138, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3970", + "gid" : 67, + "charinfo" : { "original" : 3, "before" : 3, "after" : 3 }, + "origin" : [ 1600, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-39f0", + "gid" : 67, + "charinfo" : { "original" : 4, "before" : 4, "after" : 4 }, + "origin" : [ 2062, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3a70", + "gid" : 67, + "charinfo" : { "original" : 5, "before" : 5, "after" : 5 }, + "origin" : [ 2524, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3af0", + "gid" : 67, + "charinfo" : { "original" : 6, "before" : 6, "after" : 6 }, + "origin" : [ 2986, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3b70", + "gid" : 36, + "charinfo" : { "original" : 7, "before" : 7, "after" : 7 }, + "origin" : [ 3448, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 676, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + } + ], + "postshift" : [ 0, 0 ] + }, + "cursor" : "4691-00-3870" + }, + { + "considered" : [ + { "id" : 2, "failed" : false, "input" : { "start" : "4691-00-3870", "length" : 1 } } + ], + "output" : { + "range" : { "start" : "4691-00-3870", "end" : "4691-00-38f0" }, + "slots" : [ + { + "id" : "4691-00-3870", + "gid" : 37, + "charinfo" : { "original" : 1, "before" : 1, "after" : 1 }, + "origin" : [ 676, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 694, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + } + ], + "postshift" : [ 232, 0 ] + }, + "cursor" : "4691-00-3870" + }, + { + "considered" : [ + { "id" : 1, "failed" : false, "input" : { "start" : "4691-00-38f0", "length" : 1 } } + ], + "output" : { + "range" : { "start" : "4691-00-38f0", "end" : "0000-00-0000" }, + "slots" : [ + { + "id" : "4691-00-3cf0", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 1 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3c70", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 1 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3bf0", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 2 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-38f0", + "gid" : 67, + "charinfo" : { "original" : 2, "before" : 2, "after" : 2 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3970", + "gid" : 67, + "charinfo" : { "original" : 3, "before" : 3, "after" : 3 }, + "origin" : [ 1832, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-39f0", + "gid" : 67, + "charinfo" : { "original" : 4, "before" : 4, "after" : 4 }, + "origin" : [ 2294, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3a70", + "gid" : 67, + "charinfo" : { "original" : 5, "before" : 5, "after" : 5 }, + "origin" : [ 2756, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3af0", + "gid" : 67, + "charinfo" : { "original" : 6, "before" : 6, "after" : 6 }, + "origin" : [ 3218, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3b70", + "gid" : 36, + "charinfo" : { "original" : 7, "before" : 7, "after" : 7 }, + "origin" : [ 3680, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 676, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + } + ], + "postshift" : [ 0, 0 ] + }, + "cursor" : "0000-00-0000" + } + ] + } + ], + "outputdir" : "ltr", + "output" : [ + { + "id" : "4691-01-37f0", + "gid" : 36, + "charinfo" : { "original" : 0, "before" : 0, "after" : 0 }, + "origin" : [ 0, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 676, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3870", + "gid" : 37, + "charinfo" : { "original" : 1, "before" : 1, "after" : 1 }, + "origin" : [ 676, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 694, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3cf0", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 1 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3c70", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 1 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3bf0", + "gid" : 0, + "charinfo" : { "original" : 2, "before" : 1, "after" : 2 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 0, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-38f0", + "gid" : 67, + "charinfo" : { "original" : 2, "before" : 2, "after" : 2 }, + "origin" : [ 1370, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3970", + "gid" : 67, + "charinfo" : { "original" : 3, "before" : 3, "after" : 3 }, + "origin" : [ 1832, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-39f0", + "gid" : 67, + "charinfo" : { "original" : 4, "before" : 4, "after" : 4 }, + "origin" : [ 2294, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3a70", + "gid" : 67, + "charinfo" : { "original" : 5, "before" : 5, "after" : 5 }, + "origin" : [ 2756, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3af0", + "gid" : 67, + "charinfo" : { "original" : 6, "before" : 6, "after" : 6 }, + "origin" : [ 3218, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 462, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + }, + { + "id" : "4691-00-3b70", + "gid" : 36, + "charinfo" : { "original" : 7, "before" : 7, "after" : 7 }, + "origin" : [ 3680, 0 ], + "shift" : [ 0, 0 ], + "advance" : [ 676, 0 ], + "insert" : true, + "break" : 30, + "user" : [] + } + ], + "advance" : [ 0, 0 ], + "chars" : [ + { "offset" : 0, "unicode" : 98, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 1, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 2, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 3, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 4, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 5, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 6, "unicode" : 97, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } }, + { "offset" : 7, "unicode" : 98, "break" : 30, "flags" : 0, "slot" : { "before" : -1, "after" : -1 } } + ] + } +]
tests/standards/underflow.log+2 −0 added@@ -0,0 +1,2 @@ +Text codes + 62 61 61 61 61 61 61 62
Vulnerability mechanics
Root cause
"An integer underflow in the slotat macro allows for an out-of-bounds write."
Attack vector
An attacker can trigger this vulnerability by providing crafted Graphite actions. The `slotat` macro does not ensure that an offset is within the allowed slot-map range, leading to an integer underflow. This underflow can result in an out-of-bounds write, potentially leading to a crash or arbitrary code execution. The vulnerability is triggered by a specific input file, `underflow.ttf` [ref_id=1].
Affected code
The vulnerability lies within the `slotat` macro, defined in the Graphite source code. The original macro `slotat(x)` directly used the offset `x` to access the `map` array without validation. The fix introduces a check to ensure the calculated address `map + (x)` is within the bounds of the slot map before dereferencing it [patch_id=4887178].
What the fix does
The patch modifies the `slotat` macro to include bounds checking before accessing the map. It now verifies if `map + (x)` is within the valid range of `smap.end()`. If the offset is out of bounds, it sets the status to `Machine::slot_offset_out_bounds` instead of performing an unsafe memory access [patch_id=4887178]. This prevents the integer underflow and subsequent out-of-bounds write.
Preconditions
- inputA specially crafted Graphite font file that triggers the integer underflow.
Generated on Jun 5, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.