Title: [277232] trunk/Source/WebCore
Revision
277232
Author
mmaxfi...@apple.com
Date
2021-05-08 17:13:59 -0700 (Sat, 08 May 2021)

Log Message

Add bounds checks around calls to GlyphBuffer::stringOffsetAt()
https://bugs.webkit.org/show_bug.cgi?id=225335
<rdar://problem/75663608>

Reviewed by Simon Fraser and Geoff Garen.

We're getting crash reports that look like they're from string offsets being out-of-bounds.
These string offsets round-trip through Core Text, which is allowed to modify them, which
can end up making them out-of-bounds.

No new tests because I don't have a reproducible test case; just crash reports.

* platform/graphics/FontCascade.cpp:
(WebCore::computeUnderlineType):
* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBuffer::uncheckedStringOffsetAt const):
(WebCore::GlyphBuffer::checkedStringOffsetAt const):
(WebCore::GlyphBuffer::stringOffsetAt const): Deleted.
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::applyFontTransforms):
(WebCore::WidthIterator::applyExtraSpacingAfterShaping):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (277231 => 277232)


--- trunk/Source/WebCore/ChangeLog	2021-05-08 22:35:07 UTC (rev 277231)
+++ trunk/Source/WebCore/ChangeLog	2021-05-09 00:13:59 UTC (rev 277232)
@@ -1,3 +1,27 @@
+2021-05-08  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        Add bounds checks around calls to GlyphBuffer::stringOffsetAt()
+        https://bugs.webkit.org/show_bug.cgi?id=225335
+        <rdar://problem/75663608>
+
+        Reviewed by Simon Fraser and Geoff Garen.
+
+        We're getting crash reports that look like they're from string offsets being out-of-bounds.
+        These string offsets round-trip through Core Text, which is allowed to modify them, which
+        can end up making them out-of-bounds.
+
+        No new tests because I don't have a reproducible test case; just crash reports.
+
+        * platform/graphics/FontCascade.cpp:
+        (WebCore::computeUnderlineType):
+        * platform/graphics/GlyphBuffer.h:
+        (WebCore::GlyphBuffer::uncheckedStringOffsetAt const):
+        (WebCore::GlyphBuffer::checkedStringOffsetAt const):
+        (WebCore::GlyphBuffer::stringOffsetAt const): Deleted.
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::applyFontTransforms):
+        (WebCore::WidthIterator::applyExtraSpacingAfterShaping):
+
 2021-05-08  Ricky Mondello  <rmonde...@apple.com>
 
         Fix a typo

Modified: trunk/Source/WebCore/platform/graphics/FontCascade.cpp (277231 => 277232)


--- trunk/Source/WebCore/platform/graphics/FontCascade.cpp	2021-05-08 22:35:07 UTC (rev 277231)
+++ trunk/Source/WebCore/platform/graphics/FontCascade.cpp	2021-05-09 00:13:59 UTC (rev 277232)
@@ -1154,15 +1154,14 @@
     // so we want to draw through CJK characters (on a character-by-character basis).
     // FIXME: The CSS spec says this should instead be done by the user-agent stylesheet using the lang= attribute.
     UChar32 baseCharacter;
-    auto offsetInString = glyphBuffer.stringOffsetAt(index);
-
-    GlyphBufferStringOffset textRunLength = textRun.length();
-    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(offsetInString < textRunLength);
+    auto offsetInString = glyphBuffer.checkedStringOffsetAt(index, textRun.length());
+    if (!offsetInString)
+        return GlyphUnderlineType::SkipDescenders;
     
     if (textRun.is8Bit())
-        baseCharacter = textRun.characters8()[offsetInString];
+        baseCharacter = textRun.characters8()[offsetInString.value()];
     else
-        U16_GET(textRun.characters16(), 0, offsetInString, textRunLength, baseCharacter);
+        U16_GET(textRun.characters16(), 0, static_cast<unsigned>(offsetInString.value()), textRun.length(), baseCharacter);
     
     // u_getIntPropertyValue with UCHAR_IDEOGRAPHIC doesn't return true for Japanese or Korean codepoints.
     // Instead, we can use the "Unicode allocation block" for the character.

Modified: trunk/Source/WebCore/platform/graphics/GlyphBuffer.h (277231 => 277232)


--- trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-05-08 22:35:07 UTC (rev 277231)
+++ trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-05-09 00:13:59 UTC (rev 277232)
@@ -74,7 +74,14 @@
     Glyph glyphAt(unsigned index) const { return m_glyphs[index]; }
     GlyphBufferAdvance advanceAt(unsigned index) const { return m_advances[index]; }
     GlyphBufferOrigin originAt(unsigned index) const { return m_origins[index]; }
-    GlyphBufferStringOffset stringOffsetAt(unsigned index) const { return m_offsetsInString[index]; }
+    GlyphBufferStringOffset uncheckedStringOffsetAt(unsigned index) const { return m_offsetsInString[index]; }
+    Optional<GlyphBufferStringOffset> checkedStringOffsetAt(unsigned index, unsigned stringLength) const
+    {
+        auto result = uncheckedStringOffsetAt(index);
+        if (result < 0 || static_cast<unsigned>(result) >= stringLength)
+            return WTF::nullopt;
+        return result;
+    }
 
     void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; }
     const GlyphBufferAdvance& initialAdvance() const { return m_initialAdvance; }

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (277231 => 277232)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-05-08 22:35:07 UTC (rev 277231)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-05-09 00:13:59 UTC (rev 277232)
@@ -115,7 +115,7 @@
     }
 
     for (unsigned i = lastGlyphCount; i < glyphBufferSize; ++i) {
-        auto characterIndex = glyphBuffer.stringOffsetAt(i);
+        auto characterIndex = glyphBuffer.uncheckedStringOffsetAt(i);
         auto iterator = std::lower_bound(charactersTreatedAsSpace.begin(), charactersTreatedAsSpace.end(), characterIndex, [](const OriginalAdvancesForCharacterTreatedAsSpace& l, GlyphBufferStringOffset r) -> bool {
             return l.stringOffset < r;
         });
@@ -395,9 +395,11 @@
     Vector<Optional<GlyphIndexRange>> characterIndexToGlyphIndexRange(m_run.length(), WTF::nullopt);
     Vector<float> advanceWidths(m_run.length(), 0);
     for (unsigned i = glyphBufferStartIndex; i < glyphBuffer.size(); ++i) {
-        auto stringOffset = glyphBuffer.stringOffsetAt(i);
-        advanceWidths[stringOffset] += width(glyphBuffer.advanceAt(i));
-        auto& glyphIndexRange = characterIndexToGlyphIndexRange[stringOffset];
+        auto stringOffset = glyphBuffer.checkedStringOffsetAt(i, m_run.length());
+        if (!stringOffset)
+            continue;
+        advanceWidths[stringOffset.value()] += width(glyphBuffer.advanceAt(i));
+        auto& glyphIndexRange = characterIndexToGlyphIndexRange[stringOffset.value()];
         if (glyphIndexRange)
             glyphIndexRange->trailingGlyphIndex = i;
         else
@@ -409,9 +411,8 @@
         for (unsigned i = glyphBufferStartIndex; i < glyphBuffer.size(); ++i) {
             // All characters' advances get stretched, except apparently tab characters...
             // This doesn't make much sense, because even tab characters get letter-spacing...
-            auto stringOffset = glyphBuffer.stringOffsetAt(i);
-            auto character = m_run[stringOffset];
-            if (character == tabCharacter)
+            auto stringOffset = glyphBuffer.checkedStringOffsetAt(i, m_run.length());
+            if (stringOffset && m_run[stringOffset.value()] == tabCharacter)
                 continue;
 
             auto currentAdvance = width(glyphBuffer.advanceAt(i));
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to