CVE-2026-8577
Overview
Files Changed
DEPSthird_party/harfbuzz-ng/README.chromiumthird_party/harfbuzz-ng/src
Patch
From 8047bc4000b040350d0532e0e99e1c13f550e0a3 Mon Sep 17 00:00:00 2001
From: Dominik Röttsches <drott@chromium.org>
Date: Fri, 27 Mar 2026 03:56:56 -0700
Subject: [PATCH] Roll src/third_party/harfbuzz-ng/src/ 6f4c5cec3..4fc961392 (27 commits)
Contains improvements for security issue reported in crbug.com/496302307.
https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git/+log/6f4c5cec306d..4fc96139259e
$ git log 6f4c5cec3..4fc961392 --date=short --no-merges --format='%ad %ae %s'
2026-03-26 behdad [AGENTS.md] Allow Co-Authored-By
2026-03-26 behdad [vector] Use clear() instead of resize(0)/shrink(0) (#5876)
2026-03-26 behdad [raster] Guard direct SVG paint callbacks
2026-03-26 behdad [vector] Destruct items in clear() when vector is in error state
2026-03-26 behdad [gpos] Guard cursive attachment reversal
2026-03-26 behdad [raster] Increase max image buffer size
2026-03-25 behdad Remove two redundant conditionals
2026-03-24 behdad [glyf] Reject simple glyphs with too few points
2026-03-24 behdad [font] Fix typo in setting design coords (#5871)
2026-03-24 behdad [font] Avoid div-by-zero in parent scale
2026-03-24 behdad [font] Avoid creating a cycle in set_parent()
2026-03-24 behdad [zlib] Remove unused macro
2026-03-24 behdad Ignore -Warray-bounds
2026-03-23 behdad [vector] Fix clear() when vector is in error state
2026-03-23 behdad [raster] Use png_jmpbuf in PNG error callback (#5868)
2026-03-23 49699333+dependabot[bot] Bump hendrikmuhs/ccache-action from 1.2.20 to 1.2.21
2026-03-23 49699333+dependabot[bot] Bump github/codeql-action from 4.33.0 to 4.34.1
2026-03-22 behdad [buffer] Bounds-check in add_utf() (#5864)
2026-03-21 62257866+dejanyy [ot-font] Skip adjusting offsets when all origin values are zero (#5863)
2026-03-21 62257866+dejanyy Fix for issue #5847 (#5862)
2026-03-20 behdad Add a fuzzer test
2026-03-19 behdad Revert "[rust] Use design coords if available, to set on the Rust side"
2026-03-19 behdad [rust] Use design coords if available, to set on the Rust side
2026-03-19 behdad [vector] Reject errored SVG paint bodies
2026-03-19 behdad [vector] Fail closed on SVG paint body OOM
2026-03-19 behdad Add a fuzzer font
2026-03-19 behdad [docs] Note failing-malloc in fuzzing guidance
Created with:
roll-dep src/third_party/harfbuzz-ng/src
R=behdad@chromium.org,bungeman@chromium.org,drott@chromium.org,jshin@chromium.org,kojii@chromium.org
Fixed: 496302307
Change-Id: Ifb38a46c9e129cf5701559e112032e77839405f7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7705953
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
Commit-Queue: Dominik Röttsches <drott@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1606081}
---
diff --git a/DEPS b/DEPS
index c140d42..b6a147aa4 100644
--- a/DEPS
+++ b/DEPS
@@ -363,7 +363,7 @@
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling HarfBuzz
# and whatever else without interference from each other.
- 'harfbuzz_revision': '6f4c5cec306d31e6822303f5ba248a14293d588e',
+ 'harfbuzz_revision': '4fc96139259ebc35f40118e0382ac8037d928e5c',
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling Emoji Segmenter
# and whatever else without interference from each other.
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium
index b1b4c66..976a591 100644
--- a/third_party/harfbuzz-ng/README.chromium
+++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,10 +1,10 @@
Name: harfbuzz-ng
Short Name: harfbuzz-ng
URL: http://harfbuzz.org
-Version: 13.2.1-0
+Version: 13.2.1-28
CPEPrefix: cpe:/a:harfbuzz_project:harfbuzz:13.2.1
-Date: 2026-03-19
-Revision: 6f4c5cec306d31e6822303f5ba248a14293d588e
+Date: 2026-03-27
+Revision: 4fc96139259ebc35f40118e0382ac8037d928e5c
Update Mechanism: Manual
Security Critical: yes
Shipped: yes
diff --git a/third_party/harfbuzz-ng/src b/third_party/harfbuzz-ng/src
index 6f4c5ce..4fc9613 160000
--- a/third_party/harfbuzz-ng/src
+++ b/third_party/harfbuzz-ng/src
@@ -1 +1 @@
-Subproject commit 6f4c5cec306d31e6822303f5ba248a14293d588e
+Subproject commit 4fc96139259ebc35f40118e0382ac8037d928e5c
Original Bug Report
Potential negation overflow in HarfBuzz reverse_cursive_minor_offset leading to OOB access
Project Fortify, an experimental security project, has identified the following potential security issue.
Overview: A negation overflow in HarfBuzz’s cursive attachment logic occurs when an attachment chain distance is exactly INT16_MIN (-32768). This bypasses truncation checks and leads to a massive out-of-bounds array access when the chain is reversed. On 32-bit platforms, this wraps to a predictable negative offset, potentially allowing reliable heap underflow writes and renderer RCE.
Affected files:
third_party/harfbuzz-ng/src/src/OT/Layout/GPOS/CursivePosFormat1.hh
Estimated timestamp from git blame: 2025-11-03
Summary
A potential vulnerability exists in HarfBuzz’s OpenType Layout engine (third_party/harfbuzz-ng/src/src/OT/Layout/GPOS/CursivePosFormat1.hh). A negation overflow can corrupt a glyph’s attachment chain, leading to out-of-bounds (OOB) memory accesses.
Because HarfBuzz processes untrusted web fonts inside the renderer process, and the affected array (hb_glyph_position_t *pos) is a raw C-style pointer unprotected by MiraclePtr (BackupRefPtr), this bug can be weaponized. On 64-bit systems, it causes a deterministic crash (Denial of Service). On 32-bit systems (like Chrome on 32-bit Android), integer wrapping turns this into a reliable heap underflow write, providing a strong primitive for Remote Code Execution (RCE).
Root Cause Analysis
The vulnerability stems from the handling of the 16-bit signed integer attach_chain().
- The Bypass: In
CursivePosFormat1::apply, the distance between a parent and child glyph is calculated and stored. If a Left-to-Right layout attaches a parent at index0to a child at index32768, the distance is0 - 32768 = -32768. Because-32768(INT16_MIN) perfectly fits into the signed 16-bitattach_chain()field, it survives the truncation guard check (pos[child].attach_chain() != (int) parent - (int) child) at line 234. - The Negation Overflow: When a subsequent Right-to-Left lookup forces HarfBuzz to reverse the attachment tree, it calls
reverse_cursive_minor_offset(). At line 75, it attempts to invert the chain direction:pos[j].attach_chain() = -chain;. Sincechainis-32768,-chainbecomes32768. Assigning32768to theint16_tfield overflows the maximum positive value (32767), wrapping back to-32768. - The OOB Access: The chain is now corrupted. When the engine traverses this chain again, it calculates the next index at line 62:
unsigned int j = (int) i + chain;. Ifi = 0andchain = -32768,jbecomes-32768, which casts to the unsigned integer4294934528. This massive index is then used for recursive reads and writes, such aspos[j].attach_chain() = -chain.
Platform Specific Impact
- 64-bit Platforms: The array element size is 20 bytes.
4294934528 * 20bytes results in an offset of approximately 85.8 GB. Accessing this address deterministically hits unmapped memory, crashing the renderer (DoS). - 32-bit Platforms: The pointer arithmetic (
4294934528 * 20) is constrained to 32 bits. Mathematically,0xFFFF8000 * 0x14wraps to0xFFF60000. Interpreted as a signed 32-bit offset, this is exactly-655360bytes. This creates a highly predictable640 KBheap underflow.
Suggested Attacker Steps
(Note: These are potential steps based on static analysis, as our setup does not run live exploit code.)
- Create a web page embedding a malicious OpenType font and a text string that generates a HarfBuzz buffer of at least 32,769 glyphs.
- Groom the 32-bit renderer heap such that attacker-controlled data is placed exactly 640 KB before the target HarfBuzz buffer allocation. Ensure this memory contains specific bytes to pass the early-return check (
type & ATTACH_TYPE_CURSIVE). - Trigger a Left-to-Right
CursivePosFormat1lookup linking glyph0and glyph32768to plant the-32768chain value. - Trigger a Right-to-Left
CursivePosFormat1lookup to reverse the chain, triggering the negation overflow and corrupting the chain. - Trigger another lookup to traverse the corrupted chain. The engine will perform an OOB read at the groomed
-640 KBoffset, followed by OOB writes (e.g., writing0and negated offsets) to that same location. - Use these OOB write primitives to corrupt adjacent object metadata or vtables, leading to renderer RCE.
Suggested Fix
- Reject INT16_MIN: In
CursivePosFormat1::apply, explicitly reject assignments where the calculated distance is-32768(since its negation cannot be represented in 16 bits). - Bounds Checking: Add an explicit bounds check inside
reverse_cursive_minor_offset()right after computingj = (int) i + chainto verify thatj < buffer->lenbefore performing any recursive calls or array accesses. (Similar to the checks inpropagate_attachment_offsets()).
Evaluated with Chrome root at commit: a3f5fcb392f2902650ca2b71820e7e418787e18b
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. Please feel free to reach out to me if you have concerns or feedback.