CVE-2026-9960
Overview
Files Changed
DEPSthird_party/freetype/README.chromiumthird_party/freetype/src
Patch
From 987ad3f070b881386cb161401cb678a7933ad693 Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
Date: Thu, 21 May 2026 09:04:07 -0700
Subject: [PATCH] [M148] Roll src/third_party/freetype/src/ 99b479dc3..6d9fc45fc (39 commits)
https://chromium.googlesource.com/chromium/src/third_party/freetype2.git/+log/99b479dc3472..6d9fc45fc4bc
$ git log 99b479dc3..6d9fc45fc --date=short --no-merges --format='%ad %ae %s'
2026-04-28 apodtele * src/truetype/ttgxvar.c (tt_delta_shift): Use unsigned references.
2026-04-27 apodtele [truetype/GX] Fix signed overflow.
2026-04-26 apodtele [truetype] Reduce zone copying.
2026-04-26 apodtele [truetype] Simplify shift conditions.
2026-04-26 apodtele * src/truetype/ttinterp.c (Move_Zp2_Point): Remove 'touch'.
2026-04-26 apodtele [truetype] Fix SHZ according to specifications.
2026-04-23 apodtele * src/truetype/ttinterp.c (Ins_SHZ): Fix the range limit (cont'd).
2026-04-22 apodtele * src/truetype/ttinterp.c (Ins_SHZ): Fix the range limit.
2026-04-22 apodtele * src/truetype/ttinterp.c (Ins_IUP): Use unsigned counter.
2026-04-22 yarikos [build] Add a Plan 9 port.
2026-04-21 apodtele * include/freetype/fttypes.h: Do not include stddef.h.
2026-04-21 wl * src/sfnt/ttsbit.c (tt_face_load_sbix_image): Use `FT_MulDiv`.
2026-04-21 apodtele * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use unsigned counts.
2026-04-12 apodtele * src/truetype/ttdriver.cv (tt_glyph_load): Remover redundancies.
2026-04-12 apodtele * src/sdf/ftsdf.c (sdf_*_to): Remover redundant checks.
2026-04-12 apodtele [pcf] Limit bitmap allocation and loading.
2026-04-11 apodtele * src/smooth/ftsmooth.c (ft_smooth_raster_lcd): Fix clip_box.
2026-04-11 apodtele * src/type1/t1parse.c (T1_Get_Private_Dict): Minor.
2026-04-03 wl [autofit] Prevent signed integer overflow.
2026-04-02 wl [hvf] Correctly initialize driver if no HVF library is available.
2026-04-02 wl [autofit] Prevent signed integer overflow.
2025-11-21 mpsuzuki Update some VisualStudio project files to include HVF module.
2026-03-02 goldsmit * builds/unix/configure.raw: Handle new HVF driver.
2026-03-02 goldsmit * meson.build, meson_option.txt: Handle new HVF driver.
2026-03-02 goldsmit * CMakeLists.txt: Handle new HVF driver.
2026-03-03 goldsmit Support Hierarchical Variable Fonts (HVF) using Apple's 'libhvf' library.
2026-03-03 goldsmit Add flag `FT_CONFIG_OPTION_HVF`.
2026-03-23 apodtele * src/truetype/ttinterp.c (TT_MulFix14_i386): Typo.
2026-03-24 rudi * src/base/ftstroke.c (ft_stroke_border_get_counts): Remove variable.
2026-03-22 wl * Version 2.14.3 released. ==========================
2026-03-22 wl * subprojects/harfbuzz.wrap: Updated.
2026-03-22 david.pokora [psaux] Avoid stack overflow.
2026-03-22 wl * src/psaux/t1decide.c (t1_decoder_parse_charstrings): Fix bounds check.
2026-03-20 wl ttnameid.h: Minor documentation improvement.
2026-03-20 wl * src/sdf/ftsdf.c (sdf_generate_bounding_box): Fix thinko.
2026-03-19 apodtele [sfnt/COLRv0] Revise sanity checks.
2026-03-19 apodtele * src/truetype/ttgload.c (TT_Process_Composite_Glyph): Fix allocation.
2026-03-18 wl * src/sdf/ftsdf.c (sdf_generate_bounding_box): Fix allocation.
2026-03-11 wl Update all copyright notices.
Created with:
roll-dep src/third_party/freetype/src
Bug: 504573260
Fixed: 514925499
Change-Id: I9f2f585b05720f502df3023619bb0303eda62a8f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7862315
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Auto-Submit: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/branch-heads/7778@{#3401}
Cr-Branched-From: 77f495ee216d4c3cc784d33658bad4778c0680ee-refs/heads/main@{#1610480}
---
diff --git a/DEPS b/DEPS
index 649faa13..c1221080 100644
--- a/DEPS
+++ b/DEPS
@@ -359,7 +359,7 @@
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling freetype
# and whatever else without interference from each other.
- 'freetype_revision': '99b479dc34728936b006679a31e12b8cf432fc55',
+ 'freetype_revision': '6d9fc45fc4bca8aef0b8f65592520673638c3334',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling HarfBuzz
# and whatever else without interference from each other.
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 54344809..00ed1d09 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
Name: FreeType
URL: http://www.freetype.org/
-Version: VER-2-14-2-19-g99b479dc3
-Revision: 99b479dc34728936b006679a31e12b8cf432fc55
+Version: VER-2-14-3-29-g6d9fc45fc
+Revision: 6d9fc45fc4bca8aef0b8f65592520673638c3334
Update Mechanism: Manual
CPEPrefix: cpe:/a:freetype:freetype:2.14.2
License: FTL
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 99b479d..6d9fc45 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 99b479dc34728936b006679a31e12b8cf432fc55
+Subproject commit 6d9fc45fc4bca8aef0b8f65592520673638c3334
Original Bug Report
Potential Heap OOB Write in FreeType tt_interpolate_deltas via integer overflow
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: A signed 16-bit integer overflow in FreeType’s tt_interpolate_deltas loop counter can bypass bounds checks when processing composite glyphs with 32,768 or more contours. This leads to a heap out-of-bounds read, supplying a manipulated endpoint to tt_delta_shift, which subsequently allows an attacker to perform a heap out-of-bounds write. This is reachable in Chromium via the sandboxed PrintCompositor process.
Affected files:
third_party/freetype/src/src/truetype/ttgxvar.cthird_party/freetype/src/src/truetype/ttgload.cthird_party/freetype/src/include/freetype/ftimage.h
Estimated timestamp from git blame: 2015-05-31
Summary
A signed 16-bit integer overflow in FreeType’s tt_interpolate_deltas function leads to heap out-of-bounds (OOB) reads and writes. The function uses a signed FT_Short for its contour loop counter, while the total number of contours (n_contours) is an unsigned short. When a composite glyph contains 32,768 or more contours, the counter overflows to a negative value, bypassing the loop termination condition due to C integer promotion rules. This leads to an OOB read of an endpoint array, which is then used as an upper bound in a subsequent loop (tt_delta_shift), enabling a heap OOB write. This code path is reachable in Chromium’s sandboxed PrintCompositor process via malicious Skia serialized pictures.
Vulnerability Details
The vulnerability exists in third_party/freetype/src/src/truetype/ttgxvar.c within the tt_interpolate_deltas function:
FT_Short contour;
...
contour = 0;
do {
end_point = outline->contours[contour]; // OOB Read when contour < 0
...
contour++;
} while ( contour < outline->n_contours ); // unsigned short n_contours
FT_Short is a signed 16-bit integer. FreeType limits the total number of contours (n_contours) to USHRT_MAX (65,535). If an attacker crafts a font with 32,768 or more contours, the contour variable increments until it reaches 32,767. On the next increment, it wraps around to -32,768.
Under C integer promotion rules, the comparison contour < outline->n_contours promotes both the signed short (-32,768) and the unsigned short (e.g., 32,768) to 32-bit signed ints. The comparison (int)-32,768 < (int)32,768 evaluates to true, and the loop erroneously continues with a negative index.
This results in an OOB read of outline->contours[-32768]. The value read becomes end_point. If the attacker has groomed the heap such that this memory location contains a large value, it can be passed to functions like tt_delta_shift:
// tt_delta_shift OOB write sink in ttgxvar.c
for ( p = ref + 1; p <= p2; p++ ) // p2 is the attacker-controlled end_point
{
out_points[p].x += delta.x;
out_points[p].y += delta.y;
}
Because tt_delta_shift lacks bounds checking against the pool buffer holding out_points, the loop will process points far past the end of the allocation. The attacker controls delta.x and delta.y via the gvar table, granting a powerful OOB addition primitive against adjacent heap structures.
Reachability in Chromium
This vulnerability is reachable via the PrintCompositor utility process, which renders page contents to PDF. An attacker who has compromised a renderer process can serialize an SkPicture object containing a font descriptor.
By manually setting the Skia font FactoryId in the serialized stream to SkSetFourByteTag('f','r','e','e') (SkTypeface_FreeType::FactoryId), the attacker bypasses Web Font (OTS) sanitization. The PrintCompositor process invokes SkPicture::MakeFromStream, which resolves the ID and calls SkTypeface_FreeType::MakeFromStream. This directly initializes the malicious font via FreeType (FT_Open_Face). When the SkPicture is rasterized, the vulnerable variation processing path is triggered.
Potential Exploitation Steps
Note: These are suggested steps based on static analysis; a working Proof-of-Concept has not been run.
- Gain code execution within a sandboxed renderer process.
- Construct a TrueType font containing a composite glyph with at least 32,768 contours. Include a
gvartable with variation deltas for this glyph. - Serialize an
SkPicturethat references this font, manually setting theFactoryIdin the binary stream to'free'. - Groom the heap in the
PrintCompositorprocess (e.g., via IPC spray) to place a large 16-bit value exactly 65,536 bytes before the anticipatedoutline->contoursallocation. - Send the
SkPicturetoPrintCompositorvia themojom::PrintCompositor::CompositePageIPC interface. - The
PrintCompositordeserializes the payload, triggers the OOB read to fetch the large endpoint, and then performs OOB writes (addprimitive), corrupting adjacent heap objects (e.g., vtables) to hijack control flow.
Proposed Fix
In third_party/freetype/src/src/truetype/ttgxvar.c, update the type of the contour local variable in tt_interpolate_deltas to an FT_Int or an unsigned short so that it safely accommodates the maximum possible value of outline->n_contours without overflowing.
Evaluated with Chrome root at commit: 7353d249d9cacf9c7218e1d7b8a39cf39c72d646
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.