[packages/xorg-lib-libXfont] Rel 3. Fixes: CVE-2026-56001, CVE-2026-56002, CVE-2026-56003, CVE-2026-59679, CVE-2026-44950

arekm arekm at pld-linux.org
Sun Oct 18 12:21:28 CEST 2026


commit 990b60679e8e8da47802580215703643f5637d73
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Sun Oct 18 12:20:58 2026 +0200

    Rel 3. Fixes: CVE-2026-56001, CVE-2026-56002, CVE-2026-56003, CVE-2026-59679, CVE-2026-44950

 CVE-2026-44950.patch   |  92 ++++++++++++++++++++++++++++++++
 CVE-2026-56001.patch   |  82 ++++++++++++++++++++++++++++
 CVE-2026-56002.patch   | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
 CVE-2026-56003.patch   | 110 ++++++++++++++++++++++++++++++++++++++
 CVE-2026-59679.patch   |  89 +++++++++++++++++++++++++++++++
 xorg-lib-libXfont.spec |  19 ++++---
 6 files changed, 528 insertions(+), 6 deletions(-)
---
diff --git a/xorg-lib-libXfont.spec b/xorg-lib-libXfont.spec
index 61fbad7..228edae 100644
--- a/xorg-lib-libXfont.spec
+++ b/xorg-lib-libXfont.spec
@@ -2,11 +2,16 @@ Summary:	X font library used by the X server
 Summary(pl.UTF-8):	Używana przez X serwer biblioteka fontów X
 Name:		xorg-lib-libXfont
 Version:	1.5.4
-Release:	2
+Release:	3
 License:	MIT
 Group:		X11/Libraries
 Source0:	https://xorg.freedesktop.org/releases/individual/lib/libXfont-%{version}.tar.bz2
 # Source0-md5:	16eaf156edd79b68038b6a7c44aa9e9b
+Patch0:		CVE-2026-56001.patch
+Patch1:		CVE-2026-56002.patch
+Patch2:		CVE-2026-56003.patch
+Patch3:		CVE-2026-59679.patch
+Patch4:		CVE-2026-44950.patch
 URL:		https://xorg.freedesktop.org/
 BuildRequires:	autoconf >= 2.60
 BuildRequires:	automake
@@ -51,10 +56,7 @@ Group:		X11/Development/Libraries
 Requires:	%{name} = %{version}-%{release}
 Requires:	bzip2-devel
 Requires:	freetype-devel >= 2
-Requires:	xorg-lib-libfontenc-devel
-Requires:	xorg-lib-xtrans-devel
 Requires:	xorg-proto-fontsproto-devel >= 2.1.3
-Requires:	xorg-proto-xproto-devel
 Requires:	zlib-devel
 Obsoletes:	libXfont-devel
 
@@ -89,6 +91,11 @@ Pakiet zawiera statyczną bibliotekę libXfont.
 
 %prep
 %setup -q -n libXfont-%{version}
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
 
 %build
 %{__libtoolize}
@@ -119,12 +126,12 @@ rm -rf $RPM_BUILD_ROOT
 %defattr(644,root,root,755)
 %doc AUTHORS COPYING ChangeLog README
 %attr(755,root,root) %{_libdir}/libXfont.so.*.*.*
-%attr(755,root,root) %ghost %{_libdir}/libXfont.so.1
+%ghost %{_libdir}/libXfont.so.1
 
 %files devel
 %defattr(644,root,root,755)
 %doc doc/*.html
-%attr(755,root,root) %{_libdir}/libXfont.so
+%{_libdir}/libXfont.so
 %{_includedir}/X11/fonts/bdfint.h
 %{_includedir}/X11/fonts/bitmap.h
 %{_includedir}/X11/fonts/bufio.h
diff --git a/CVE-2026-44950.patch b/CVE-2026-44950.patch
new file mode 100644
index 0000000..5c3eb24
--- /dev/null
+++ b/CVE-2026-44950.patch
@@ -0,0 +1,92 @@
+From c2d222bb22c623d8a40f3275077fc7e6617f2c8a Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 13 Jul 2026 15:50:09 +1000
+Subject: [PATCH] fserve: bounds-check cumulative glyph data writes in
+ fs_read_glyphs
+
+fs_read_glyphs() copies each glyph's bitmap into a single allbits
+buffer allocated to rep->nbytes bytes. The per-glyph guard validates
+only that the source slice (position, length) lies within the pbitmaps
+source buffer. It does not check whether the running destination cursor
+has exceeded the allocation.
+
+A malicious font server can send overlapping source offsets (e.g. 1000
+glyphs each referencing {position:0, length:64} with nbytes=64). Each
+individual source range passes validation, but the cumulative writes
+total 64000 bytes into a 64-byte destination buffer.
+
+Interestingly there was an unconditional debug printf in place that
+sort-of warned about this but didn't prevent this. Let's remove that and
+instead use the actual check to bail out before we run OOB.
+
+A regression test is included that sends 100 glyphs each referencing
+the same 64-byte source slice into a 64-byte destination buffer, and
+verifies the library rejects the overflow.
+
+CVE-2026-44950
+
+Found-by: Zhixi "Jace" Sun, independent security researcher
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/36>
+---
+ src/fc/fserve.c                | 23 +++++++++------
+ test/test-fserve-read-glyphs.c | 52 +++++++++++++++++++++++++++++++---
+ 2 files changed, 62 insertions(+), 13 deletions(-)
+
+diff --git a/src/fc/fserve.c b/src/fc/fserve.c
+index 744a68c..3e479a9 100644
+--- a/src/fc/fserve.c
++++ b/src/fc/fserve.c
+@@ -1900,10 +1900,7 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+     fsOffset32		    local_off;
+     char		    *off_adr;
+     pointer		    pbitmaps;
+-    char		    *bits, *allbits;
+-#ifdef DEBUG
+-    char		    *origallbits;
+-#endif
++    char		    *bits, *allbits, *origallbits;
+     int			    i,
+ 			    err;
+     int			    nranges = 0;
+@@ -2004,8 +2001,8 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+ 	goto bail;
+     }
+ 
+-#ifdef DEBUG
+     origallbits = allbits;
++#ifdef DEBUG
+     fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n",
+ 	     (int) rep->num_chars, (int) rep->nbytes, fsd->name);
+ #endif
+@@ -2036,6 +2033,18 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+ 		    (local_off.position < rep->nbytes) &&
+ 		    (local_off.length <= (rep->nbytes - local_off.position)))
+ 		{
++		    /* Check that the destination buffer has enough room
++		       for this glyph to prevent a heap overflow from
++		       overlapping source offsets. */
++		    if (local_off.length >
++			rep->nbytes - (allbits - origallbits))
++		    {
++			ErrorF("fserve: glyph data overflow: "
++			       "cumulative write exceeds nbytes (%u)\n",
++			       (unsigned) rep->nbytes);
++			err = AllocError;
++			goto bail;
++		    }
+ 		    bits = allbits;
+ 		    allbits += local_off.length;
+ 		    memcpy(bits, (char *)pbitmaps + local_off.position,
+@@ -2063,10 +2072,6 @@ fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec)
+ 	}
+ 	off_adr += SIZEOF(fsOffset32);
+     }
+-#ifdef DEBUG
+-    fprintf (stderr, "Used %d bytes instead of %d\n",
+-	     (int) (allbits - origallbits), (int) rep->nbytes);
+-#endif
+ 
+     if (blockrec->type == FS_OPEN_FONT)
+     {
diff --git a/CVE-2026-56001.patch b/CVE-2026-56001.patch
new file mode 100644
index 0000000..c7cbee2
--- /dev/null
+++ b/CVE-2026-56001.patch
@@ -0,0 +1,82 @@
+From be0b08e2d354138d3222b4490e2a77c6ee42f778 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 1 Jun 2026 16:46:10 +1000
+Subject: [PATCH] bitscale: fix integer overflow in BitmapScaleBitmaps
+ bytestoalloc
+
+bytestoalloc is declared as unsigned int (32-bit). When the sum of
+per-glyph byte counts exceeds 2^32, the value wraps around and calloc()
+allocates a buffer that is too small. The subsequent ScaleBitmap loop
+then writes past the end of the allocated buffer.
+
+Change bytestoalloc from unsigned int to size_t to match the actual
+allocation size type, and add an explicit overflow check in the
+accumulation loop to bail out if the total would exceed SIZE_MAX.
+
+This vulnerability was discovered by:
+Anonymous working with TrendAI Zero Day Initiative
+
+CVE-2026-56001/ZDI-CAN-30558
+
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/34>
+---
+ src/bitmap/bitscale.c | 25 +++++++++++++++++++++-----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+diff --git a/src/bitmap/bitscale.c b/src/bitmap/bitscale.c
+index 3f3c10e..5f465d1 100644
+--- a/src/bitmap/bitscale.c
++++ b/src/bitmap/bitscale.c
+@@ -38,6 +38,7 @@
+ #include <X11/fonts/bitmap.h>
+ #include <X11/fonts/fontutil.h>
+ #include <math.h>
++#include <stdint.h>
+ 
+ #ifndef MAX
+ #define   MAX(a,b)    (((a)>(b)) ? a : b)
+@@ -1456,7 +1456,7 @@ BitmapScaleBitmaps(FontPtr pf,          /* scaled font */
+ 		opci;
+     FontInfoPtr pfi;
+     int         glyph;
+-    unsigned    bytestoalloc = 0;
++    size_t      bytestoalloc = 0;
+     int		firstCol, lastCol, firstRow, lastRow;
+ 
+     double	xform[4], inv_xform[4];
+@@ -1483,8 +1483,25 @@ BitmapScaleBitmaps(FontPtr pf,          /* scaled font */
+     glyph = pf->glyph;
+     for (i = 0; i < nchars; i++)
+     {
+-	if ((pci = ACCESSENCODING(bitmapFont->encoding, i)))
+-	    bytestoalloc += BYTES_FOR_GLYPH(pci, glyph);
++	if ((pci = ACCESSENCODING(bitmapFont->encoding, i))) {
++	    size_t glyphsize = BYTES_FOR_GLYPH(pci, glyph);
++	    if (bytestoalloc > SIZE_MAX - glyphsize) {
++		fprintf(stderr,
++			"Error: bitmap allocation overflow for scaled font\n");
++		goto bail;
++	    }
++	    bytestoalloc += glyphsize;
++	}
++    }
++
++    /* Reject unreasonably large bitmap allocations that could result
++     * from malicious fonts with extreme scale factors.  256 MiB is
++     * far beyond any legitimate scaled bitmap font. */
++#define BITMAP_SCALE_MAX_ALLOC	(256 * 1024 * 1024)
++    if (bytestoalloc > BITMAP_SCALE_MAX_ALLOC) {
++	fprintf(stderr,
++		"Error: scaled bitmap size %zu exceeds limit\n", bytestoalloc);
++	goto bail;
+     }
+ 
+     /* Do we add the font malloc stuff for VALUE ADDED ? */
+@@ -1517 +1534 @@ BitmapScaleBitmaps(FontPtr pf,          /* scaled font */
+- fprintf(stderr, "Error: Couldn't allocate bitmaps (%d)\n", bytestoalloc);
++ fprintf(stderr, "Error: Couldn't allocate bitmaps (%zu)\n", bytestoalloc);
+-- 
+GitLab
+
diff --git a/CVE-2026-56002.patch b/CVE-2026-56002.patch
new file mode 100644
index 0000000..68c7b8d
--- /dev/null
+++ b/CVE-2026-56002.patch
@@ -0,0 +1,142 @@
+From b4389e0b1d84a690b819bb27b1439968811a3674 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 1 Jun 2026 16:48:40 +1000
+Subject: [PATCH] pcfread: validate bitmap sizes and offsets against per-glyph
+ metrics
+
+pcfReadFont() uses bitmapSizes[] read directly from the PCF file to
+allocate the repadded bitmap buffer. However, per-glyph metrics (also
+from the file) control how much data RepadBitmap() writes. A malicious
+PCF font can declare a small bitmapSizes[] value while having per-glyph
+metrics that require more space, causing a heap buffer overflow.
+
+A similar issue happens with the encoding offsets: pcfReadFont reads
+encoding offsets from the PCF file and uses them to index into the
+metrics array without bounds checking.  A crafted font can set an
+encoding offset larger than nmetrics, causing an out-of-bounds pointer
+that is later dereferenced when glyphs are accessed through the encoding
+table.
+
+And the no-repad bitmap path (when PCF_GLYPH_PAD matches the requested
+glyph pad) only validated that each glyph's offset was within the bitmap
+buffer, but did not check that the full glyph extent (offset +
+BYTES_PER_ROW * height) fits within the buffer.  A crafted font with a
+glyph offset near the end of a small bitmap buffer but large glyph
+metrics causes a heap buffer over-read when the glyph is later rendered.
+
+This vulnerability was discovered by:
+  Anonymous working with TrendAI Zero Day Initiative
+
+CVE-2026-56002/ZDI-CAN-30559
+
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/34>
+---
+ src/bitmap/pcfread.c | 59 +++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 56 insertions(+), 3 deletions(-)
+
+diff --git a/src/bitmap/pcfread.c b/src/bitmap/pcfread.c
+index 7c2e7e1..a385331 100644
+--- a/src/bitmap/pcfread.c
++++ b/src/bitmap/pcfread.c
+@@ -43,6 +43,7 @@
+ #endif
+ 
+ #include <stdarg.h>
++#include <limits.h>
+ #include <stdint.h>
+ #include <string.h>
+ 
+@@ -532,25 +532,74 @@ pcfReadFont(FontPtr pFont, FontFilePtr file,
+ 	int         old,
+ 	            new;
+ 	xCharInfo  *metric;
++	int         srcPad = PCF_GLYPH_PAD(format);
+ 
+-	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
+-	padbitmaps = malloc(sizepadbitmaps);
++	/* Compute the actual required size from per-glyph metrics instead
++	 * of trusting the file's bitmapSizes[] value, which may be smaller
++	 * than the actual data written by RepadBitmap. */
++	sizepadbitmaps = 0;
++	for (i = 0; i < nbitmaps; i++) {
++	    int w, h, glyphBytes;
++	    metric = &metrics[i].metrics;
++	    w = metric->rightSideBearing - metric->leftSideBearing;
++	    h = metric->ascent + metric->descent;
++	    glyphBytes = BYTES_PER_ROW(w, glyph) * h;
++	    if (glyphBytes < 0 || (glyphBytes > 0 && sizepadbitmaps > INT_MAX - glyphBytes)) {
++		pcfError("pcfReadFont(): bitmap size overflow\n");
++		goto Bail;
++	    }
++	    sizepadbitmaps += glyphBytes;
++	}
++	padbitmaps = malloc(sizepadbitmaps ? sizepadbitmaps : 1);
+ 	if (!padbitmaps) {
+           pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
+ 	    goto Bail;
+ 	}
+ 	new = 0;
+ 	for (i = 0; i < nbitmaps; i++) {
++	    int srcGlyphBytes;
++
+ 	    old = offsets[i];
+ 	    metric = &metrics[i].metrics;
++
++	    /* Validate source offset and source glyph size against the
++	     * source bitmap buffer to prevent out-of-bounds reads. */
++	    srcGlyphBytes = BYTES_PER_ROW(
++		metric->rightSideBearing - metric->leftSideBearing,
++		srcPad) * (metric->ascent + metric->descent);
++	    if (old < 0 || old > sizebitmaps ||
++		srcGlyphBytes < 0 || srcGlyphBytes > sizebitmaps - old) {
++		pcfError("pcfReadFont(): bitmap offset/size out of bounds\n");
++		free(padbitmaps);
++		goto Bail;
++	    }
++
+ 	    offsets[i] = new;
+ 	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
+-			       PCF_GLYPH_PAD(format), glyph,
++			       srcPad, glyph,
+ 			  metric->rightSideBearing - metric->leftSideBearing,
+ 			       metric->ascent + metric->descent);
+ 	}
+ 	free(bitmaps);
+ 	bitmaps = padbitmaps;
++    } else {
++	/* Validate offsets and full glyph extents against bitmap buffer */
++	for (i = 0; i < nbitmaps; i++) {
++	    int glyphBytes;
++	    xCharInfo *metric = &metrics[i].metrics;
++
++	    glyphBytes = BYTES_PER_ROW(
++		metric->rightSideBearing - metric->leftSideBearing,
++		glyph) * (metric->ascent + metric->descent);
++	    if (offsets[i] >= (CARD32)sizebitmaps ||
++		glyphBytes < 0 ||
++		glyphBytes > sizebitmaps - (int)offsets[i]) {
++		pcfError("pcfReadFont(): bitmap offset/size out of bounds "
++			 "(offset %u, size %d, total %d)\n",
++			 offsets[i], glyphBytes, sizebitmaps);
++		goto Bail;
++	    }
++	}
+     }
+     for (i = 0; i < nbitmaps; i++)
+ 	metrics[i].bits = bitmaps + offsets[i];
+@@ -625,6 +674,10 @@ pcfReadFont(FontPtr pFont, FontFilePtr file,
+ 	if (IS_EOF(file)) goto Bail;
+ 	if (encodingOffset == 0xFFFF) {
+ 	    pFont->info.allExist = FALSE;
++	} else if (encodingOffset >= nmetrics) {
++	    pcfError("pcfReadFont(): encoding offset %d out of range (nmetrics=%d)\n",
++		     encodingOffset, nmetrics);
++	    goto Bail;
+ 	} else {
+             if(!encoding[SEGMENT_MAJOR(i)]) {
+                 encoding[SEGMENT_MAJOR(i)]=
+-- 
+GitLab
+
diff --git a/CVE-2026-56003.patch b/CVE-2026-56003.patch
new file mode 100644
index 0000000..139002d
--- /dev/null
+++ b/CVE-2026-56003.patch
@@ -0,0 +1,110 @@
+From dff957a5158da038a282a59a31fe736702732939 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Mon, 1 Jun 2026 16:49:55 +1000
+Subject: [PATCH] bitscale: add bounds check to computeProps for property
+ buffer
+
+ComputeScaledProperties allocates a fixed-size property buffer of 70
+slots. computeProps iterates the source font's properties and writes 1
+slot for unscaled properties or 2 slots for scaledX/scaledY properties,
+with no bounds check. A malicious font with many duplicate properties
+matching fontPropTable entries can overflow the allocated buffer.
+
+Fix this by passing the remaining buffer capacity to computeProps and
+checking it before each write. Properties that would exceed the buffer
+are silently skipped.
+
+The function is also restructured to handle the buffer writes for
+scaledX/scaledY inside the switch cases directly, rather than in a
+separate block after the switch. This makes the control flow clearer and
+ensures the bounds check covers all writes.
+
+This vulnerability was discovered by:
+Anonymous working with TrendAI Zero Day Initiative
+
+CVE-2026-56003/ZDI-CAN-30560
+
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/34>
+---
+ src/bitmap/bitscale.c | 39 ++++++++++++++++++++-------------------
+ 1 file changed, 20 insertions(+), 19 deletions(-)
+
+diff --git a/src/bitmap/bitscale.c b/src/bitmap/bitscale.c
+index 5f465d1..ec57f55 100644
+--- a/src/bitmap/bitscale.c
++++ b/src/bitmap/bitscale.c
+@@ -507,7 +507,8 @@ static int
+ computeProps(FontPropPtr pf, char *wasStringProp,
+ 	     FontPropPtr npf, char *isStringProp,
+ 	     unsigned int nprops, double xfactor, double yfactor,
+-	     double sXfactor, double sYfactor)
++	     double sXfactor, double sYfactor,
++	     int maxprops)
+ {
+     int         n;
+     int         count;
+@@ -522,14 +523,26 @@ computeProps(FontPropPtr pf, char *wasStringProp,
+ 
+ 	switch (t->type) {
+ 	case scaledX:
+-	    npf->value = doround(xfactor * (double)pf->value);
+-	    rawfactor = sXfactor;
+-	    break;
+ 	case scaledY:
+-	    npf->value = doround(yfactor * (double)pf->value);
+-	    rawfactor = sYfactor;
++	    if (count + 2 > maxprops)
++		continue;
++	    npf->value = (t->type == scaledX)
++		? doround(xfactor * (double)pf->value)
++		: doround(yfactor * (double)pf->value);
++	    rawfactor = (t->type == scaledX) ? sXfactor : sYfactor;
++	    npf->name = pf->name;
++	    npf++;
++	    count++;
++	    npf->value = doround(rawfactor * (double)pf->value);
++	    npf->name = rawFontPropTable[t - fontPropTable].atom;
++	    npf++;
++	    count++;
++	    *isStringProp++ = *wasStringProp;
++	    *isStringProp++ = *wasStringProp;
+ 	    break;
+ 	case unscaled:
++	    if (count + 1 > maxprops)
++		continue;
+ 	    npf->value = pf->value;
+ 	    npf->name = pf->name;
+ 	    npf++;
+@@ -539,18 +552,6 @@ computeProps(FontPropPtr pf, char *wasStringProp,
+ 	default:
+ 	    break;
+ 	}
+-	if (t->type != unscaled)
+-	{
+-	    npf->name = pf->name;
+-	    npf++;
+-	    count++;
+-	    npf->value = doround(rawfactor * (double)pf->value);
+-	    npf->name = rawFontPropTable[t - fontPropTable].atom;
+-	    npf++;
+-	    count++;
+-	    *isStringProp++ = *wasStringProp;
+-	    *isStringProp++ = *wasStringProp;
+-	}
+     }
+     return count;
+ }
+@@ -667,7 +668,7 @@ ComputeScaledProperties(FontInfoPtr sourceFontInfo, /* the font to be scaled */
+     n = NPROPS;
+     n += computeProps(sourceFontInfo->props, sourceFontInfo->isStringProp,
+ 		      fp, isStringProp, sourceFontInfo->nprops, dx, dy,
+-		      sdx, sdy);
++		      sdx, sdy, nProps - NPROPS);
+     return n;
+ }
+ 
+-- 
+GitLab
+
diff --git a/CVE-2026-59679.patch b/CVE-2026-59679.patch
new file mode 100644
index 0000000..2f7b0d5
--- /dev/null
+++ b/CVE-2026-59679.patch
@@ -0,0 +1,89 @@
+From 668fea81f40bcb48ec67fb55d0b851049d265290 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at 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 at who-t.net>
+Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxfont/-/merge_requests/36>
+---
+ Makefile.am                    |  20 +-
+ src/fc/fserve.c                |  22 ++
+ src/fc/fservestr.h             |   1 +
+ test/test-fserve-read-glyphs.c | 368 +++++++++++++++++++++++++++++++++
+ 4 files changed, 409 insertions(+), 2 deletions(-)
+ create mode 100644 test/test-fserve-read-glyphs.c
+
+diff --git a/src/fc/fserve.c b/src/fc/fserve.c
+index abf7d07..744a68c 100644
+--- a/src/fc/fserve.c
++++ b/src/fc/fserve.c
+@@ -1081,6 +1081,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
+@@ -1980,6 +1981,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;
+@@ -2001,6 +2013,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;
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/xorg-lib-libXfont.git/commitdiff/990b60679e8e8da47802580215703643f5637d73



More information about the pld-cvs-commit mailing list