Compare commits

...

No commits in common. "c8" and "c8-beta" have entirely different histories.
c8 ... c8-beta

7 changed files with 3 additions and 393 deletions

View File

@ -1,45 +0,0 @@
From c8c96212cf28d011f8294c66dc4bda70e9c09256 Mon Sep 17 00:00:00 2001
From: Ahmet Furkan Kavraz <kavraz@amazon.com>
Date: Wed, 7 Jan 2026 14:46:09 +0000
Subject: [PATCH] Fix CVE-2025-15279: Heap buffer overflow in BMP RLE
decompression
The readpixels() function reads RLE count values from BMP files without
validating buffer bounds. A malicious BMP can specify excessive counts
causing heap buffer overflow during pixel decompression, potentially
leading to remote code execution.
Add bounds checking after each count read to ensure ii + cnt does not
exceed the allocated buffer size (head->height * head->width). Return 0
on validation failure to trigger error handling.
CVE-2025-15279
CVSS: 7.8 (High)
ZDI-CAN-27517
---
gutils/gimagereadbmp.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/gutils/gimagereadbmp.c b/gutils/gimagereadbmp.c
index 5a137e28af..133336787c 100644
--- a/gutils/gimagereadbmp.c
+++ b/gutils/gimagereadbmp.c
@@ -181,12 +181,18 @@ static int readpixels(FILE *file,struct bmpheader *head) {
int ii = 0;
while ( ii<head->height*head->width ) {
int cnt = getc(file);
+ if (cnt < 0 || ii + cnt > head->height * head->width) {
+ return 0;
+ }
if ( cnt!=0 ) {
int ch = getc(file);
while ( --cnt>=0 )
head->byte_pixels[ii++] = ch;
} else {
cnt = getc(file);
+ if (cnt < 0 || ii + cnt > head->height * head->width) {
+ return 0;
+ }
if ( cnt>= 3 ) {
int odd = cnt&1;
while ( --cnt>=0 )

View File

@ -1,28 +0,0 @@
From 9edd1cc5223d959687ccfd834433af5e830c56c2 Mon Sep 17 00:00:00 2001
From: Ahmet Furkan Kavraz <kavraz@amazon.com>
Date: Thu, 8 Jan 2026 08:42:53 +0000
Subject: [PATCH] Fix CVE-2025-15275: Heap buffer overflow in SFD image parsing
Validate clutlen parameter (0-256) before use to prevent heap buffer
overflow when writing to fixed-size clut array.
Fixes: CVE-2025-15275 | ZDI-25-1189 | ZDI-CAN-28543
---
fontforge/sfd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/fontforge/sfd.c b/fontforge/sfd.c
index 6b980a4785..0590c119f3 100644
--- a/fontforge/sfd.c
+++ b/fontforge/sfd.c
@@ -3653,6 +3653,10 @@ static ImageList *SFDGetImage(FILE *sfd) {
getint(sfd,&image_type);
getint(sfd,&bpl);
getint(sfd,&clutlen);
+ if ( clutlen < 0 || clutlen > 256 ) {
+ LogError(_("Invalid clut length %d in sfd file, must be between 0 and 256"), clutlen);
+ return NULL;
+ }
gethex(sfd,&trans);
image = GImageCreate(image_type,width,height);
base = image->list_len==0?image->u.image:image->u.images[0];

View File

@ -1,27 +0,0 @@
From f99b1c886c0d9324440517a7a4253c5432e284ad Mon Sep 17 00:00:00 2001
From: Ahmet Furkan Kavraz <kavraz@amazon.com>
Date: Thu, 8 Jan 2026 15:38:57 +0000
Subject: [PATCH] Fix CVE-2025-15269: Use-after-free in SFD ligature parsing
Prevent circular linked list in LigaCreateFromOldStyleMultiple by clearing
the next pointer after shallow copy. The shallow copy propagates liga's
modified next pointer from previous iterations, creating a cycle that
causes double-free when the list is traversed and freed.
Fixes: CVE-2025-15269 | ZDI-25-1195 | ZDI-CAN-28564
---
fontforge/sfd.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fontforge/sfd.c b/fontforge/sfd.c
index 6b980a4785..48b2b5f651 100644
--- a/fontforge/sfd.c
+++ b/fontforge/sfd.c
@@ -4711,6 +4711,7 @@ static PST1 *LigaCreateFromOldStyleMultiple(PST1 *liga) {
while ( (pt = strrchr(liga->pst.u.lig.components,';'))!=NULL ) {
new = chunkalloc(sizeof( PST1 ));
*new = *liga;
+ new->pst.next = NULL;
new->pst.u.lig.components = copy(pt+1);
last->pst.next = (PST *) new;
last = new;

View File

@ -1,35 +0,0 @@
From a0eedb850e1216cece0f9be61bfd45ddfc4a719d Mon Sep 17 00:00:00 2001
From: Ahmet Furkan Kavraz <kavraz@amazon.com>
Date: Fri, 9 Jan 2026 13:39:17 +0000
Subject: [PATCH] Fix CVE-2025-15279: Move bounds check inside cnt >= 3 block
Move the bounds check to inside the 'if (cnt >= 3)' block. This fixes
the issue where cnt == 0, cnt == 1, and cnt == 2 require different ii
calculations (end-of-line, end-of-bitmap, delta) and the bounds check
before the conditional would incorrectly reject valid operations.
CVE-2025-15279
CVSS: 7.8 (High)
ZDI-CAN-27517
---
gutils/gimagereadbmp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/gutils/gimagereadbmp.c b/gutils/gimagereadbmp.c
index 133336787c..ad365158cc 100644
--- a/gutils/gimagereadbmp.c
+++ b/gutils/gimagereadbmp.c
@@ -190,10 +190,10 @@ static int readpixels(FILE *file,struct bmpheader *head) {
head->byte_pixels[ii++] = ch;
} else {
cnt = getc(file);
- if (cnt < 0 || ii + cnt > head->height * head->width) {
- return 0;
- }
if ( cnt>= 3 ) {
+ if (ii + cnt > head->height * head->width) {
+ return 0;
+ }
int odd = cnt&1;
while ( --cnt>=0 )
head->byte_pixels[ii++] = getc(file);

View File

@ -1,39 +0,0 @@
From a04b3e4d72a1709d2cd7a7dfb6552ab1fe9a9d31 Mon Sep 17 00:00:00 2001
From: Ahmet Furkan Kavraz <kavraz@amazon.com>
Date: Fri, 30 Jan 2026 09:54:28 +0000
Subject: [PATCH] Fix CVE-2025-15270: Heap buffer overflow in SFD kern class
parsing
Fixes: CVE-2025-15270 | ZDI-25-1194 | ZDI-CAN-28563
Co-authored-by: Ahmet Furkan Kavraz <kavraz@amazon.com>
---
fontforge/sfd.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fontforge/sfd.c b/fontforge/sfd.c
index 6b980a4785..78df7a8ff3 100644
--- a/fontforge/sfd.c
+++ b/fontforge/sfd.c
@@ -8275,6 +8275,10 @@ bool SFD_GetFontMetaData( FILE *sfd,
for ( i=classstart; i<kc->first_cnt; ++i ) {
if (kernclassversion < 3) {
getint(sfd,&temp);
+ if (temp < 0) {
+ LogError(_("Corrupted SFD file: Invalid kern class name length %d. Aborting load."), temp);
+ return false;
+ }
kc->firsts[i] = malloc(temp+1); kc->firsts[i][temp] = '\0';
nlgetc(sfd); /* skip space */
fread(kc->firsts[i],1,temp,sfd);
@@ -8292,6 +8296,10 @@ bool SFD_GetFontMetaData( FILE *sfd,
for ( i=1; i<kc->second_cnt; ++i ) {
if (kernclassversion < 3) {
getint(sfd,&temp);
+ if (temp < 0) {
+ LogError(_("Corrupted SFD file: Invalid kern class name length %d. Aborting load."), temp);
+ return false;
+ }
kc->seconds[i] = malloc(temp+1); kc->seconds[i][temp] = '\0';
nlgetc(sfd); /* skip space */
fread(kc->seconds[i],1,temp,sfd);

View File

@ -1,178 +0,0 @@
From a64099931ea004a08e074b08ad0984d92c25daa2 Mon Sep 17 00:00:00 2001
From: Peter Kydas <pk@canva.com>
Date: Tue, 6 Feb 2024 10:23:36 +1100
Subject: [PATCH] fix splinefont shell command injection
---
fontforge/splinefont.c | 125 +++++++++++++++++++++++++++++------------
1 file changed, 90 insertions(+), 35 deletions(-)
diff --git a/fontforge/splinefont.c b/fontforge/splinefont.c
index 239fdc035b..647daee109 100644
--- a/fontforge/splinefont.c
+++ b/fontforge/splinefont.c
@@ -788,11 +788,14 @@ return( name );
char *Unarchive(char *name, char **_archivedir) {
char *dir = getenv("TMPDIR");
- char *pt, *archivedir, *listfile, *listcommand, *unarchivecmd, *desiredfile;
+ char *pt, *archivedir, *listfile, *desiredfile;
char *finalfile;
int i;
int doall=false;
static int cnt=0;
+ gchar *command[5];
+ gchar *stdoutresponse = NULL;
+ gchar *stderrresponse = NULL;
*_archivedir = NULL;
@@ -827,18 +830,30 @@ return( NULL );
listfile = malloc(strlen(archivedir)+strlen("/" TOC_NAME)+1);
sprintf( listfile, "%s/" TOC_NAME, archivedir );
- listcommand = malloc( strlen(archivers[i].unarchive) + 1 +
- strlen( archivers[i].listargs) + 1 +
- strlen( name ) + 3 +
- strlen( listfile ) +4 );
- sprintf( listcommand, "%s %s %s > %s", archivers[i].unarchive,
- archivers[i].listargs, name, listfile );
- if ( system(listcommand)!=0 ) {
- free(listcommand); free(listfile);
- ArchiveCleanup(archivedir);
-return( NULL );
- }
- free(listcommand);
+ command[0] = archivers[i].unarchive;
+ command[1] = archivers[i].listargs;
+ command[2] = name;
+ command[3] = NULL; // command args need to be NULL-terminated
+
+ if ( g_spawn_sync(
+ NULL,
+ command,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ &stdoutresponse,
+ &stderrresponse,
+ NULL,
+ NULL
+ ) == FALSE) { // did not successfully execute
+ ArchiveCleanup(archivedir);
+ return( NULL );
+ }
+ // Write out the listfile to be read in later
+ FILE *fp = fopen(listfile, "wb");
+ fwrite(stdoutresponse, strlen(stdoutresponse), 1, fp);
+ fclose(fp);
desiredfile = ArchiveParseTOC(listfile, archivers[i].ars, &doall);
free(listfile);
@@ -847,22 +862,28 @@ return( NULL );
return( NULL );
}
- /* I tried sending everything to stdout, but that doesn't work if the */
- /* output is a directory file (ufo, sfdir) */
- unarchivecmd = malloc( strlen(archivers[i].unarchive) + 1 +
- strlen( archivers[i].listargs) + 1 +
- strlen( name ) + 1 +
- strlen( desiredfile ) + 3 +
- strlen( archivedir ) + 30 );
- sprintf( unarchivecmd, "( cd %s ; %s %s %s %s ) > /dev/null", archivedir,
- archivers[i].unarchive,
- archivers[i].extractargs, name, doall ? "" : desiredfile );
- if ( system(unarchivecmd)!=0 ) {
- free(unarchivecmd); free(desiredfile);
- ArchiveCleanup(archivedir);
-return( NULL );
+ command[0] = archivers[i].unarchive;
+ command[1] = archivers[i].extractargs;
+ command[2] = name;
+ command[3] = doall ? "" : desiredfile;
+ command[4] = NULL;
+
+ if ( g_spawn_sync(
+ (gchar*)archivedir,
+ command,
+ NULL,
+ G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ &stdoutresponse,
+ &stderrresponse,
+ NULL,
+ NULL
+ ) == FALSE) { // did not successfully execute
+ free(desiredfile);
+ ArchiveCleanup(archivedir);
+ return( NULL );
}
- free(unarchivecmd);
finalfile = malloc( strlen(archivedir) + 1 + strlen(desiredfile) + 1);
sprintf( finalfile, "%s/%s", archivedir, desiredfile );
@@ -885,20 +906,54 @@ struct compressors compressors[] = {
char *Decompress(char *name, int compression) {
char *dir = getenv("TMPDIR");
- char buf[1500];
char *tmpfn;
-
+ gchar *command[4];
+ gint stdout_pipe;
+ gchar buffer[4096];
+ gssize bytes_read;
+ GByteArray *binary_data = g_byte_array_new();
+
if ( dir==NULL ) dir = P_tmpdir;
tmpfn = malloc(strlen(dir)+strlen(GFileNameTail(name))+2);
strcpy(tmpfn,dir);
strcat(tmpfn,"/");
strcat(tmpfn,GFileNameTail(name));
*strrchr(tmpfn,'.') = '\0';
- snprintf( buf, sizeof(buf), "%s < %s > %s", compressors[compression].decomp, name, tmpfn );
- if ( system(buf)==0 )
-return( tmpfn );
- free(tmpfn);
-return( NULL );
+
+ command[0] = compressors[compression].decomp;
+ command[1] = "-c";
+ command[2] = name;
+ command[3] = NULL;
+
+ // Have to use async because g_spawn_sync doesn't handle nul-bytes in the output (which happens with binary data)
+ if (g_spawn_async_with_pipes(
+ NULL,
+ command,
+ NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &stdout_pipe,
+ NULL,
+ NULL) == FALSE) {
+ //command has failed
+ return( NULL );
+ }
+
+ // Read binary data from pipe and output to file
+ while ((bytes_read = read(stdout_pipe, buffer, sizeof(buffer))) > 0) {
+ g_byte_array_append(binary_data, (guint8 *)buffer, bytes_read);
+ }
+ close(stdout_pipe);
+
+ FILE *fp = fopen(tmpfn, "wb");
+ fwrite(binary_data->data, sizeof(gchar), binary_data->len, fp);
+ fclose(fp);
+ g_byte_array_free(binary_data, TRUE);
+
+ return(tmpfn);
}
static char *ForceFileToHaveName(FILE *file, char *exten) {

View File

@ -3,7 +3,7 @@
Name: fontforge Name: fontforge
Version: 20200314 Version: 20200314
Release: 7%{?dist} Release: 5%{?dist}
Summary: Outline and bitmap font editor Summary: Outline and bitmap font editor
License: GPLv3+ License: GPLv3+
@ -14,24 +14,6 @@ Source0: https://github.com/fontforge/%{name}/archive/%{gittag0}.tar.gz#/
Patch0: fontforge-20200314-Call-gdk_set_allowed_backends-before-gdk_init.patch Patch0: fontforge-20200314-Call-gdk_set_allowed_backends-before-gdk_init.patch
# https://github.com/fontforge/fontforge/pull/4257 # https://github.com/fontforge/fontforge/pull/4257
Patch1: fontforge-20200314-minor-backward-compatible-sphinx-changes.patch Patch1: fontforge-20200314-minor-backward-compatible-sphinx-changes.patch
# https://github.com/fontforge/fontforge/pull/5367
# Fixes CVE-2024-25081 and CVE-2024-25082
Patch2: Fix_Splinefont_shell_invocation.patch
# CVE-2025-15279 https://github.com/fontforge/fontforge/pull/5720
# https://sourceforge.net/p/fontforge/patches/32/
Patch3: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5720.patch
# CVE-2025-15275 https://github.com/fontforge/fontforge/pull/5721
# https://sourceforge.net/p/fontforge/patches/37/
Patch4: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5721.patch
# CVE-2025-15269 https://github.com/fontforge/fontforge/pull/5722
# https://sourceforge.net/p/fontforge/patches/40/
Patch5: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5722.patch
# CVE-2025-15279 https://github.com/fontforge/fontforge/pull/5723
# https://sourceforge.net/p/fontforge/patches/32/
Patch6: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5723.patch
# CVE-2025-15270 https://github.com/fontforge/fontforge/pull/5743
# https://sourceforge.net/p/fontforge/patches/41/
Patch7: https://patch-diff.githubusercontent.com/raw/fontforge/fontforge/pull/5743.patch
Requires: xdg-utils Requires: xdg-utils
Requires: autotrace Requires: autotrace
@ -87,14 +69,8 @@ This package contains documentation files for %{name}.
%prep %prep
%setup -q %setup -q
%patch -P 0 -p1 %patch0 -p1
%patch -P 1 -p1 %patch1 -p1
%patch -P 2 -p1
%patch -P 3 -p1
%patch -P 4 -p1
%patch -P 5 -p1
%patch -P 6 -p1
%patch -P 7 -p1
# Remove tests that requires Internet access # Remove tests that requires Internet access
sed -i '45d;83d;101d;102d;114d;115d;125d' tests/CMakeLists.txt sed -i '45d;83d;101d;102d;114d;115d;125d' tests/CMakeLists.txt
@ -162,20 +138,6 @@ popd
%doc %{_pkgdocdir} %doc %{_pkgdocdir}
%changelog %changelog
* Wed Mar 25 2026 Parag Nemade <pnemade AT redhat DOT com> - 20200314-7
- Resolves: RHEL-138168
CVE-2025-15270 SFD File Parsing Remote Code Execution Vulnerability
- Resolves: RHEL-138174
CVE-2025-15279 GUtils BMP File Parsing Heap-based Buffer Overflow
- Resolves: RHEL-138190
CVE-2025-15275 SFD File Parsing Heap-based Buffer Overflow
- Resolves: RHEL-138140
CVE-2025-15269 SFD File Parsing Use-After-Free
* Thu Apr 04 2024 Parag Nemade <pnemade AT redhat DOT com> - 20200314-6
- Resolves: RHEL-26715 - fontforge: various flaws
(CVE-2024-25081 and CVE-2024-25082)
* Mon Dec 14 2020 Parag Nemade <pnemade AT redhat DOT com> - 20200314-5 * Mon Dec 14 2020 Parag Nemade <pnemade AT redhat DOT com> - 20200314-5
- The %%find_lang should run as part of %%install only - The %%find_lang should run as part of %%install only