87 lines
3.0 KiB
Diff
87 lines
3.0 KiB
Diff
From 7e075dc1678e53a81ce95ba3036abeaeea1539e3 Mon Sep 17 00:00:00 2001
|
|
From: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Mon, 13 Jul 2026 15:48:06 +1000
|
|
Subject: [PATCH] fserve: validate num_chars against encoding array size in
|
|
fs_read_glyphs
|
|
|
|
FS_QueryXExtents16 causes us to allocate the encoding[] array, later
|
|
during the FS_QueryXBitmaps16 reply handling we fill in that array.
|
|
There is no verification that the allocation is large enough, a
|
|
malicious font server could send us a small numExtents and a
|
|
large num_chars to force underallocation and OOB read/rwrite.
|
|
|
|
A regression test is included that constructs a crafted
|
|
FS_QueryXBitmaps16 reply with num_chars > num_encoding and verifies
|
|
the library rejects it.
|
|
|
|
CVE-2026-59679
|
|
|
|
Found-by: Zhixi "Jace" Sun, independent security researcher
|
|
Assisted-by: Claude:claude-opus-4-6
|
|
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/36>
|
|
---
|
|
src/fc/fserve.c | 22 ++++++++++++++++++++++
|
|
src/fc/fservestr.h | 1 +
|
|
2 files changed, 23 insertions(+)
|
|
|
|
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
|
|
index 708fc35..4141c3c 100644
|
|
--- a/src/fc/fserve.c
|
|
+++ b/src/fc/fserve.c
|
|
@@ -1097,6 +1097,7 @@ fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
return AllocError;
|
|
}
|
|
fsfont->encoding = pCI;
|
|
+ fsfont->num_encoding = numExtents;
|
|
if (haveInk)
|
|
fsfont->inkMetrics = pCI + numExtents;
|
|
else
|
|
@@ -2004,6 +2005,17 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
{
|
|
minchar = 0;
|
|
maxchar = rep->num_chars;
|
|
+
|
|
+ /* Reject replies where num_chars exceeds the encoding array
|
|
+ size allocated in fs_read_extent_info() to prevent
|
|
+ out-of-bounds access on encoding[]. */
|
|
+ if (rep->num_chars > (CARD32)fsdata->num_encoding)
|
|
+ {
|
|
+ ErrorF("fserve: num_chars (%u) > num_encoding (%d)\n",
|
|
+ (unsigned) rep->num_chars, fsdata->num_encoding);
|
|
+ err = AllocError;
|
|
+ goto bail;
|
|
+ }
|
|
}
|
|
|
|
off_adr = (char *)ppbits;
|
|
@@ -2025,6 +2037,16 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
|
|
for (i = 0; i < rep->num_chars; i++)
|
|
{
|
|
memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */
|
|
+ /* Bounds-check minchar against the encoding array size to
|
|
+ prevent out-of-bounds access from a malicious font server
|
|
+ reply with more num_chars than num_extents. */
|
|
+ if (minchar >= (unsigned long)fsdata->num_encoding)
|
|
+ {
|
|
+ ErrorF("fserve: glyph index %lu >= num_encoding (%d)\n",
|
|
+ minchar, fsdata->num_encoding);
|
|
+ err = AllocError;
|
|
+ goto bail;
|
|
+ }
|
|
if (blockrec->type == FS_OPEN_FONT ||
|
|
fsdata->encoding[minchar].bits == &_fs_glyph_requested)
|
|
{
|
|
diff --git a/src/fc/fservestr.h b/src/fc/fservestr.h
|
|
index 29ae46e..da95e41 100644
|
|
--- a/src/fc/fservestr.h
|
|
+++ b/src/fc/fservestr.h
|
|
@@ -43,6 +43,7 @@ typedef struct _fs_glyph {
|
|
typedef struct _fs_font {
|
|
CharInfoPtr pDefault;
|
|
CharInfoPtr encoding;
|
|
+ int num_encoding;
|
|
CharInfoPtr inkMetrics;
|
|
FSGlyphPtr glyphs;
|
|
} FSFontRec, *FSFontPtr;
|