Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect comparison in Fonts
DescriptionIncorrect comparison in Fonts
ComponentFonts
Bug ClassLogic Error
Tracker513446410
Fix commitf62b9df71852 (chromium/src) +64/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-06

Changed Functions

FunctionChangeNotes
TEST_F
third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
modified
for
third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
modified
if
third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
modified

Files Changed

  • third_party/blink/renderer/platform/fonts/opentype/format_check.rs
  • third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
From f62b9df71852f924534c3a0492ee76edf897bb0f Mon Sep 17 00:00:00 2001
From: Dominik Röttsches <[email protected]>
Date: Fri, 18 Sep 2026 05:50:58 -0700
Subject: [PATCH] Send avar >= 2 fonts through Fontations

For safety we want to pass unknown avar2 versions through Fontations,
too, preventing unsanitized variation data from reaching native OS
parsers. Not that avar3 exists, but if we receive such a font,
we can just send it to fontations to partially use the font and
avoiding sending invalid data to system rasterizers.

Fixed: 513446410
Change-Id: Iddc86b392c08f2fe5cd4fce01ea9920acd4ac98d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8430122
Auto-Submit: Dominik Röttsches <[email protected]>
Reviewed-by: Rune Lillesveen <[email protected]>
Commit-Queue: Dominik Röttsches <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1700680}
---
diff --git a/third_party/blink/renderer/platform/fonts/opentype/format_check.rs b/third_party/blink/renderer/platform/fonts/opentype/format_check.rs
index b99f0ec8..d01b67dd 100644
--- a/third_party/blink/renderer/platform/fonts/opentype/format_check.rs
+++ b/third_party/blink/renderer/platform/fonts/opentype/format_check.rs
@@ -56,8 +56,16 @@
     Some((version.major, version.minor))
 }
 
+// https://crbug.com/513446410: For safety we want to pass unknown avar2
+// versions through fontations, too.
 pub fn is_avar2(format_info: &FontFormatInfo) -> bool {
-    matches!(&format_info.format_flags, Some(FontFormatFlags { avar_version: Some((2, _)), .. }),)
+    matches!(
+        &format_info.format_flags,
+        Some(FontFormatFlags {
+            avar_version: Some((major, _)),
+            ..
+        }) if *major >= 2,
+    )
 }
 
 fn has_tags(format_info: &FontFormatInfo, query: &[Tag]) -> bool {
diff --git a/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc b/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
index f8be3debf..6644ace 100644
--- a/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
+++ b/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
@@ -4,8 +4,11 @@
 
 #include "third_party/blink/renderer/platform/fonts/opentype/font_format_check.h"
 
+#include "base/containers/heap_array.h"
+#include "skia/ext/skia_utils_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "ui/gfx/skia_span_util.h"
 
 namespace blink {
 
@@ -62,4 +65,56 @@
   ASSERT_FALSE(format_check.IsEbdtEblcMonochromeFont());
 }
 
+TEST_F(FontFormatCheckTest, Avar1) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar1[opsz,wdth,wght].ttf");
+  FontFormatCheck format_check(font_data_);
+  ASSERT_FALSE(format_check.IsAvar2Font());
+}
+
+TEST_F(FontFormatCheckTest, Avar2) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar2[opsz,wdth,wght].ttf");
+  FontFormatCheck format_check(font_data_);
+  ASSERT_TRUE(format_check.IsAvar2Font());
+}
+
+TEST_F(FontFormatCheckTest, AvarVersion3) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar2[opsz,wdth,wght].ttf");
+  auto modified_font_bytes =
+      base::HeapArray<uint8_t>::CopiedFrom(skia::as_byte_span(*font_data_));
+
+  // Locate the 'avar' table directory entry and modify its major version to 3.
+  constexpr uint32_t kAvarTag = SkSetFourByteTag('a', 'v', 'a', 'r');
+  size_t avar_offset = 0;
+  uint16_t num_tables = (modified_font_bytes[4] << 8) | modified_font_bytes[5];
+  for (uint16_t i = 0; i < num_tables; ++i) {
+    size_t record_offset = 12 + i * 16;
+    uint32_t tag = SkSetFourByteTag(modified_font_bytes[record_offset],
+                                    modified_font_bytes[record_offset + 1],
+                                    modified_font_bytes[record_offset + 2],
+                                    modified_font_bytes[record_offset + 3]);
+    if (tag == kAvarTag) {
+      avar_offset = (modified_font_bytes[record_offset + 8] << 24) |
+                    (modified_font_bytes[record_offset + 9] << 16) |
+                    (modified_font_bytes[record_offset + 10] << 8) |
+                    modified_font_bytes[record_offset + 11];
+      break;
+    }
+  }
+  ASSERT_NE(avar_offset, 0u);
+  ASSERT_EQ(modified_font_bytes[avar_offset], 0);
+  ASSERT_EQ(modified_font_bytes[avar_offset + 1], 2);
+  modified_font_bytes[avar_offset + 1] = 3;
+
+  sk_sp<SkData> modified_data =
+      gfx::MakeSkDataFromSpanWithCopy(modified_font_bytes);
+  FontFormatCheck format_check(modified_data);
+  ASSERT_TRUE(format_check.IsAvar2Font());
+}
+
 }  // namespace blink
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc b/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
index f8be3debf..6644ace 100644
--- a/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
+++ b/third_party/blink/renderer/platform/fonts/opentype/font_format_check_test.cc
@@ -4,8 +4,11 @@
 
 #include "third_party/blink/renderer/platform/fonts/opentype/font_format_check.h"
 
+#include "base/containers/heap_array.h"
+#include "skia/ext/skia_utils_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "ui/gfx/skia_span_util.h"
 
 namespace blink {
 
@@ -62,4 +65,56 @@
   ASSERT_FALSE(format_check.IsEbdtEblcMonochromeFont());
 }
 
+TEST_F(FontFormatCheckTest, Avar1) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar1[opsz,wdth,wght].ttf");
+  FontFormatCheck format_check(font_data_);
+  ASSERT_FALSE(format_check.IsAvar2Font());
+}
+
+TEST_F(FontFormatCheckTest, Avar2) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar2[opsz,wdth,wght].ttf");
+  FontFormatCheck format_check(font_data_);
+  ASSERT_TRUE(format_check.IsAvar2Font());
+}
+
+TEST_F(FontFormatCheckTest, AvarVersion3) {
+  EnsureFontDataFromPath(test::BlinkWebTestsDir() +
+                         "/external/wpt/css/css-fonts/resources/avar/"
+                         "DesignSpaceWarpTestAvar2[opsz,wdth,wght].ttf");
+  auto modified_font_bytes =
+      base::HeapArray<uint8_t>::CopiedFrom(skia::as_byte_span(*font_data_));
+
+  // Locate the 'avar' table directory entry and modify its major version to 3.
+  constexpr uint32_t kAvarTag = SkSetFourByteTag('a', 'v', 'a', 'r');
+  size_t avar_offset = 0;
+  uint16_t num_tables = (modified_font_bytes[4] << 8) | modified_font_bytes[5];
+  for (uint16_t i = 0; i < num_tables; ++i) {
+    size_t record_offset = 12 + i * 16;
+    uint32_t tag = SkSetFourByteTag(modified_font_bytes[record_offset],
+                                    modified_font_bytes[record_offset + 1],
+                                    modified_font_bytes[record_offset + 2],
+                                    modified_font_bytes[record_offset + 3]);
+    if (tag == kAvarTag) {
+      avar_offset = (modified_font_bytes[record_offset + 8] << 24) |
+                    (modified_font_bytes[record_offset + 9] << 16) |
+                    (modified_font_bytes[record_offset + 10] << 8) |
+                    modified_font_bytes[record_offset + 11];
+      break;
+    }
+  }
+  ASSERT_NE(avar_offset, 0u);
+  ASSERT_EQ(modified_font_bytes[avar_offset], 0);
+  ASSERT_EQ(modified_font_bytes[avar_offset + 1], 2);
+  modified_font_bytes[avar_offset + 1] = 3;
+
+  sk_sp<SkData> modified_data =
+      gfx::MakeSkDataFromSpanWithCopy(modified_font_bytes);
+  FontFormatCheck format_check(modified_data);
+  ASSERT_TRUE(format_check.IsAvar2Font());
+}
+
 }  // namespace blink
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.