From af54c1986671536babb97753e5e54f7c01df7d19 Mon Sep 17 00:00:00 2001 From: Jonathan Wright Date: Thu, 13 Mar 2025 14:40:00 -0500 Subject: [PATCH] Fixes CVE-2025-27363 --- SOURCES/freetype-2.9.1-cve-2025-27363.patch | 269 ++++++++++++++++++++ SPECS/freetype.spec | 16 +- 2 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 SOURCES/freetype-2.9.1-cve-2025-27363.patch diff --git a/SOURCES/freetype-2.9.1-cve-2025-27363.patch b/SOURCES/freetype-2.9.1-cve-2025-27363.patch new file mode 100644 index 0000000..5056cb4 --- /dev/null +++ b/SOURCES/freetype-2.9.1-cve-2025-27363.patch @@ -0,0 +1,269 @@ +diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c +index 0a436a2ac..d76758465 100644 +--- a/src/truetype/ttgload.c ++++ b/src/truetype/ttgload.c +@@ -47,6 +47,20 @@ + #undef FT_COMPONENT + #define FT_COMPONENT trace_ttgload + ++ /************************************************************************** ++ * ++ * Simple glyph flags. ++ */ ++#define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */ ++#define X_SHORT_VECTOR 0x02 ++#define Y_SHORT_VECTOR 0x04 ++#define REPEAT_FLAG 0x08 ++#define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */ ++#define SAME_X 0x10 ++#define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */ ++#define SAME_Y 0x20 ++#define OVERLAP_SIMPLE 0x40 /* we ignore this value */ ++ + + /*************************************************************************/ + /* */ + +@@ -62,7 +77,7 @@ + #define WE_HAVE_A_2X2 0x0080 + #define WE_HAVE_INSTR 0x0100 + #define USE_MY_METRICS 0x0200 +-#define OVERLAP_COMPOUND 0x0400 ++#define OVERLAP_COMPOUND 0x0400 /* we ignore this value */ + #define SCALED_COMPONENT_OFFSET 0x0800 + #define UNSCALED_COMPONENT_OFFSET 0x1000 + +@@ -337,7 +352,7 @@ + FT_Byte *flag, *flag_limit; + FT_Byte c, count; + FT_Vector *vec, *vec_limit; +- FT_Pos x; ++ FT_Pos x, y; + FT_Short *cont, *cont_limit, prev_cont; + FT_Int xy_size = 0; + +@@ -454,7 +469,7 @@ + goto Invalid_Outline; + + *flag++ = c = FT_NEXT_BYTE( p ); +- if ( c & 8 ) ++ if ( c & REPEAT_FLAG ) + { + if ( p + 1 > limit ) + goto Invalid_Outline; +@@ -480,31 +495,29 @@ + + for ( ; vec < vec_limit; vec++, flag++ ) + { +- FT_Pos y = 0; +- FT_Byte f = *flag; ++ FT_Pos delta = 0; ++ FT_Byte f = *flag; + + +- if ( f & 2 ) ++ if ( f & X_SHORT_VECTOR ) + { + if ( p + 1 > limit ) + goto Invalid_Outline; + +- y = (FT_Pos)FT_NEXT_BYTE( p ); +- if ( ( f & 16 ) == 0 ) +- y = -y; ++ delta = (FT_Pos)FT_NEXT_BYTE( p ); ++ if ( !( f & X_POSITIVE ) ) ++ delta = -delta; + } +- else if ( ( f & 16 ) == 0 ) ++ else if ( !( f & SAME_X ) ) + { + if ( p + 2 > limit ) + goto Invalid_Outline; + +- y = (FT_Pos)FT_NEXT_SHORT( p ); ++ delta = (FT_Pos)FT_NEXT_SHORT( p ); + } + +- x += y; ++ x += delta; + vec->x = x; +- /* the cast is for stupid compilers */ +- *flag = (FT_Byte)( f & ~( 2 | 16 ) ); + } + + /* reading the Y coordinates */ +@@ -512,35 +525,36 @@ + vec = gloader->current.outline.points; + vec_limit = vec + n_points; + flag = (FT_Byte*)outline->tags; +- x = 0; ++ y = 0; + + for ( ; vec < vec_limit; vec++, flag++ ) + { +- FT_Pos y = 0; +- FT_Byte f = *flag; ++ FT_Pos delta = 0; ++ FT_Byte f = *flag; + + +- if ( f & 4 ) ++ if ( f & Y_SHORT_VECTOR ) + { + if ( p + 1 > limit ) + goto Invalid_Outline; + +- y = (FT_Pos)FT_NEXT_BYTE( p ); +- if ( ( f & 32 ) == 0 ) +- y = -y; ++ delta = (FT_Pos)FT_NEXT_BYTE( p ); ++ if ( !( f & Y_POSITIVE ) ) ++ delta = -delta; + } +- else if ( ( f & 32 ) == 0 ) ++ else if ( !( f & SAME_Y ) ) + { + if ( p + 2 > limit ) + goto Invalid_Outline; + +- y = (FT_Pos)FT_NEXT_SHORT( p ); ++ delta = (FT_Pos)FT_NEXT_SHORT( p ); + } + +- x += y; +- vec->y = x; ++ y += delta; ++ vec->y = y; ++ + /* the cast is for stupid compilers */ +- *flag = (FT_Byte)( f & FT_CURVE_TAG_ON ); ++ *flag = (FT_Byte)( f & ON_CURVE_POINT ); + } + + outline->n_points = (FT_Short)n_points; +-- +diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c +index 39d9c3f..61e6a19 100644 +--- a/src/truetype/ttgload.c ++++ b/src/truetype/ttgload.c +@@ -1837,31 +1837,22 @@ + if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || + FT_IS_VARIATION( FT_FACE( face ) ) ) + { +- short i, limit; ++ FT_UShort i, limit; + FT_SubGlyph subglyph; + +- FT_Outline outline; +- FT_Vector* points = NULL; +- char* tags = NULL; +- short* contours = NULL; +- ++ FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; + +- limit = (short)gloader->current.num_subglyphs; ++ limit = (FT_UShort)gloader->current.num_subglyphs; + + /* construct an outline structure for */ + /* communication with `TT_Vary_Apply_Glyph_Deltas' */ +- outline.n_points = (short)( gloader->current.num_subglyphs + 4 ); +- outline.n_contours = outline.n_points; +- +- outline.points = NULL; +- outline.tags = NULL; +- outline.contours = NULL; +- +- if ( FT_NEW_ARRAY( points, outline.n_points ) || +- FT_NEW_ARRAY( tags, outline.n_points ) || +- FT_NEW_ARRAY( contours, outline.n_points ) ) ++ if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) || ++ FT_QNEW_ARRAY( outline.tags, limit ) || ++ FT_QNEW_ARRAY( outline.contours, limit ) ) + goto Exit1; + ++ outline.n_contours = outline.n_points = limit; ++ + subglyph = gloader->current.subglyphs; + + for ( i = 0; i < limit; i++, subglyph++ ) +@@ -1975,38 +1967,16 @@ + /* applying deltas for anchor points doesn't make sense, */ + /* but we don't have to specially check this since */ + /* unused delta values are zero anyways */ +- points[i].x = subglyph->arg1; +- points[i].y = subglyph->arg2; +- tags[i] = 1; +- contours[i] = i; ++ outline.points[i].x = subglyph->arg1; ++ outline.points[i].y = subglyph->arg2; ++ outline.tags[i] = ON_CURVE_POINT; ++ outline.contours[i] = i; + } + +- points[i].x = loader->pp1.x; +- points[i].y = loader->pp1.y; +- tags[i] = 1; +- contours[i] = i; +- +- i++; +- points[i].x = loader->pp2.x; +- points[i].y = loader->pp2.y; +- tags[i] = 1; +- contours[i] = i; +- +- i++; +- points[i].x = loader->pp3.x; +- points[i].y = loader->pp3.y; +- tags[i] = 1; +- contours[i] = i; +- +- i++; +- points[i].x = loader->pp4.x; +- points[i].y = loader->pp4.y; +- tags[i] = 1; +- contours[i] = i; +- +- outline.points = points; +- outline.tags = tags; +- outline.contours = contours; ++ outline.points[i++] = loader->pp1; ++ outline.points[i++] = loader->pp2; ++ outline.points[i++] = loader->pp3; ++ outline.points[i ] = loader->pp4; + + /* this call provides additional offsets */ + /* for each component's translation */ +@@ -2024,20 +1994,20 @@ + { + if ( subglyph->flags & ARGS_ARE_XY_VALUES ) + { +- subglyph->arg1 = (FT_Int16)points[i].x; +- subglyph->arg2 = (FT_Int16)points[i].y; ++ subglyph->arg1 = (FT_Int16)outline.points[i].x; ++ subglyph->arg2 = (FT_Int16)outline.points[i].y; + } + } + +- loader->pp1.x = points[i + 0].x; +- loader->pp1.y = points[i + 0].y; +- loader->pp2.x = points[i + 1].x; +- loader->pp2.y = points[i + 1].y; +- +- loader->pp3.x = points[i + 2].x; +- loader->pp3.y = points[i + 2].y; +- loader->pp4.x = points[i + 3].x; +- loader->pp4.y = points[i + 3].y; ++ loader->pp1.x = outline.points[i + 0].x; ++ loader->pp1.y = outline.points[i + 0].y; ++ loader->pp2.x = outline.points[i + 1].x; ++ loader->pp2.y = outline.points[i + 1].y; ++ ++ loader->pp3.x = outline.points[i + 2].x; ++ loader->pp3.y = outline.points[i + 2].y; ++ loader->pp4.x = outline.points[i + 3].x; ++ loader->pp4.y = outline.points[i + 3].y; + + /* recalculate linear horizontal and vertical advances */ + /* if we don't have HVAR and VVAR, respectively */ + + diff --git a/SPECS/freetype.spec b/SPECS/freetype.spec index ba024a6..00cab5f 100644 --- a/SPECS/freetype.spec +++ b/SPECS/freetype.spec @@ -3,7 +3,7 @@ Summary: A free and portable font rendering engine Name: freetype Version: 2.9.1 -Release: 9%{?dist} +Release: 9%{?dist}.alma.1 License: (FTL or GPLv2+) and BSD and MIT and Public Domain and zlib with acknowledgement Group: System Environment/Libraries URL: http://www.freetype.org @@ -42,6 +42,14 @@ Patch11: freetype-2.9.1-properly-guard-face-index.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2077985 Patch12: freetype-2.9.1-guard-face-size.patch +# CVE-2025-27363 +# https://issues.redhat.com/browse/RHEL-83280 +# https://gitlab.com/redhat/centos-stream/rpms/freetype/-/merge_requests/8 +# backported from +# https://gitlab.freedesktop.org/freetype/freetype/-/commit/ef636696524b081f1b8819eb0c6a0b932d35757d +# https://gitlab.freedesktop.org/freetype/freetype/-/commit/73720c7c9958e87b3d134a7574d1720ad2d24442 +Patch13: freetype-2.9.1-cve-2025-27363.patch + BuildRequires: libX11-devel BuildRequires: libpng-devel BuildRequires: zlib-devel @@ -106,6 +114,7 @@ popd %patch10 -p1 -b .windres %patch11 -p1 -b .properly-guard-face-index %patch12 -p1 -b .guard-face-size +%patch13 -p1 -b .cve-2025-27363 %build @@ -218,6 +227,11 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/*.{a,la} %{_mandir}/man1/* %changelog +* Wed Mar 12 2025 Jonathan Wright - 2.9.1-9.alma.1 +- Backport from CentOS Stream 9 PR by Michel Lind +- TrueType clean up and unsigned fixes for CVE-2025-27363 +- Resolves: RHEL-83280 + * Fri May 27 2022 Marek Kasik - 2.9.1-9 - Guard face->size - Resolves: #2079279