Title: [199890] trunk/Source/WebCore
Revision
199890
Author
cdu...@apple.com
Date
2016-04-22 12:24:42 -0700 (Fri, 22 Apr 2016)

Log Message

Crash under FontCache::purgeInactiveFontData()
https://bugs.webkit.org/show_bug.cgi?id=156822
<rdar://problem/25373970>

Reviewed by Darin Adler.

In some rare cases, the Font constructor would mutate the FontPlatformData
that is being passed in. This is an issue because because our FontCache
uses the FontPlatformData as key for the cached fonts. This could lead to
crashes because the WTFMove() in FontCache::purgeInactiveFontData() would
nullify values in our HashMap but we would then fail to remove them from
the HashMap (because the key did not match). We would then reference the
null font when looping again when doing font->hasOneRef().

This patch marks Font::m_platformData member as const to avoid such issues
in the future and moves the code altering the FontPlatformData from the
Font constructor into the FontPlatformData constructor. The purpose of
that code was to initialize FontPlatformData::m_cgFont in case the CGFont
passed in the constructor was null.

* platform/graphics/Font.h:
* platform/graphics/FontCache.cpp:
(WebCore::FontCache::fontForPlatformData):
(WebCore::FontCache::purgeInactiveFontData):
* platform/graphics/FontPlatformData.cpp:
(WebCore::FontPlatformData::FontPlatformData):
* platform/graphics/FontPlatformData.h:
* platform/graphics/cocoa/FontCocoa.mm:
(WebCore::webFallbackFontFamily): Deleted.
(WebCore::Font::platformInit): Deleted.
* platform/graphics/cocoa/FontPlatformDataCocoa.mm:
(WebCore::webFallbackFontFamily):
(WebCore::FontPlatformData::setFallbackCGFont):
* platform/graphics/win/FontPlatformDataCGWin.cpp:
(WebCore::FontPlatformData::setFallbackCGFont):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (199889 => 199890)


--- trunk/Source/WebCore/ChangeLog	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/ChangeLog	2016-04-22 19:24:42 UTC (rev 199890)
@@ -1,5 +1,43 @@
 2016-04-22  Chris Dumez  <cdu...@apple.com>
 
+        Crash under FontCache::purgeInactiveFontData()
+        https://bugs.webkit.org/show_bug.cgi?id=156822
+        <rdar://problem/25373970>
+
+        Reviewed by Darin Adler.
+
+        In some rare cases, the Font constructor would mutate the FontPlatformData
+        that is being passed in. This is an issue because because our FontCache
+        uses the FontPlatformData as key for the cached fonts. This could lead to
+        crashes because the WTFMove() in FontCache::purgeInactiveFontData() would
+        nullify values in our HashMap but we would then fail to remove them from
+        the HashMap (because the key did not match). We would then reference the
+        null font when looping again when doing font->hasOneRef().
+
+        This patch marks Font::m_platformData member as const to avoid such issues
+        in the future and moves the code altering the FontPlatformData from the
+        Font constructor into the FontPlatformData constructor. The purpose of
+        that code was to initialize FontPlatformData::m_cgFont in case the CGFont
+        passed in the constructor was null.
+
+        * platform/graphics/Font.h:
+        * platform/graphics/FontCache.cpp:
+        (WebCore::FontCache::fontForPlatformData):
+        (WebCore::FontCache::purgeInactiveFontData):
+        * platform/graphics/FontPlatformData.cpp:
+        (WebCore::FontPlatformData::FontPlatformData):
+        * platform/graphics/FontPlatformData.h:
+        * platform/graphics/cocoa/FontCocoa.mm:
+        (WebCore::webFallbackFontFamily): Deleted.
+        (WebCore::Font::platformInit): Deleted.
+        * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
+        (WebCore::webFallbackFontFamily):
+        (WebCore::FontPlatformData::setFallbackCGFont):
+        * platform/graphics/win/FontPlatformDataCGWin.cpp:
+        (WebCore::FontPlatformData::setFallbackCGFont):
+
+2016-04-22  Chris Dumez  <cdu...@apple.com>
+
         Support disabling at runtime IndexedDB constructors exposed to workers
         https://bugs.webkit.org/show_bug.cgi?id=156883
 

Modified: trunk/Source/WebCore/platform/graphics/Font.h (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/Font.h	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/Font.h	2016-04-22 19:24:42 UTC (rev 199890)
@@ -229,7 +229,7 @@
     float m_maxCharWidth;
     float m_avgCharWidth;
 
-    FontPlatformData m_platformData;
+    const FontPlatformData m_platformData;
 
     mutable RefPtr<GlyphPage> m_glyphPageZero;
     mutable HashMap<unsigned, RefPtr<GlyphPage>> m_glyphPages;

Modified: trunk/Source/WebCore/platform/graphics/FontCache.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/FontCache.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/FontCache.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -396,6 +396,8 @@
     if (addResult.isNewEntry)
         addResult.iterator->value = Font::create(platformData);
 
+    ASSERT(addResult.iterator->value->platformData() == platformData);
+
     return *addResult.iterator->value;
 }
 
@@ -435,8 +437,10 @@
         // Fonts may ref other fonts so we loop until there are no changes.
         if (fontsToDelete.isEmpty())
             break;
-        for (auto& font : fontsToDelete)
-            cachedFonts().remove(font->platformData());
+        for (auto& font : fontsToDelete) {
+            bool success = cachedFonts().remove(font->platformData());
+            ASSERT_UNUSED(success, success);
+        }
     };
 
     Vector<FontPlatformDataCacheKey> keysToRemove;

Modified: trunk/Source/WebCore/platform/graphics/FontPlatformData.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/FontPlatformData.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/FontPlatformData.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -58,6 +58,8 @@
     : FontPlatformData(size, syntheticBold, syntheticOblique, orientation, widthVariant, textRenderingMode)
 {
     m_cgFont = cgFont;
+    if (!m_cgFont)
+        setFallbackCGFont();
 }
 #endif
 

Modified: trunk/Source/WebCore/platform/graphics/FontPlatformData.h (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/FontPlatformData.h	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/FontPlatformData.h	2016-04-22 19:24:42 UTC (rev 199890)
@@ -216,6 +216,9 @@
 #if PLATFORM(WIN)
     void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
 #endif
+#if USE(CG)
+    void setFallbackCGFont();
+#endif
 
 public:
     bool m_syntheticBold { false };

Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm	2016-04-22 19:24:42 UTC (rev 199890)
@@ -79,13 +79,7 @@
     return false;
 }
 
-#if USE(APPKIT)
-static NSString *webFallbackFontFamily(void)
-{
-    static NSString *webFallbackFontFamily = [[[NSFont systemFontOfSize:16.0f] familyName] retain];
-    return webFallbackFontFamily;
-}
-#else
+#if !USE(APPKIT)
 bool fontFamilyShouldNotBeUsedForArabic(CFStringRef fontFamilyName)
 {
     if (!fontFamilyName)
@@ -104,59 +98,6 @@
 #if USE(APPKIT)
     m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
 
-    bool failedSetup = false;
-    if (!platformData().cgFont()) {
-        // Ack! Something very bad happened, like a corrupt font.
-        // Try looking for an alternate 'base' font for this renderer.
-
-        // Special case hack to use "Times New Roman" in place of "Times".
-        // "Times RO" is a common font whose family name is "Times".
-        // It overrides the normal "Times" family font.
-        // It also appears to have a corrupt regular variant.
-        NSString *fallbackFontFamily;
-        if ([[m_platformData.nsFont() familyName] isEqual:@"Times"])
-            fallbackFontFamily = @"Times New Roman";
-        else
-            fallbackFontFamily = webFallbackFontFamily();
-        
-        // Try setting up the alternate font.
-        // This is a last ditch effort to use a substitute font when something has gone wrong.
-#if !ERROR_DISABLED
-        RetainPtr<NSFont> initialFont = m_platformData.nsFont();
-#endif
-        if (m_platformData.font())
-            m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:fallbackFontFamily]);
-        else
-            m_platformData.setNSFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
-        if (!platformData().cgFont()) {
-            if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
-                // OK, couldn't setup Times New Roman as an alternate to Times, fallback
-                // on the system font.  If this fails we have no alternative left.
-                m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:webFallbackFontFamily()]);
-                if (!platformData().cgFont()) {
-                    // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
-                    LOG_ERROR("unable to initialize with font %@", initialFont.get());
-                    failedSetup = true;
-                }
-            } else {
-                // We tried the requested font and the system font. No joy. We have to give up.
-                LOG_ERROR("unable to initialize with font %@", initialFont.get());
-                failedSetup = true;
-            }
-        }
-
-        // Report the problem.
-        LOG_ERROR("Corrupt font detected, using %@ in place of %@.",
-            [m_platformData.nsFont() familyName], [initialFont.get() familyName]);
-    }
-
-    // If all else fails, try to set up using the system font.
-    // This is probably because Times and Times New Roman are both unavailable.
-    if (failedSetup) {
-        m_platformData.setNSFont([NSFont systemFontOfSize:[m_platformData.nsFont() pointSize]]);
-        LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
-    }
-
 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100
     // Work around <rdar://problem/19433490>
     CGGlyph dummyGlyphs[] = {0, 0};

Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm	2016-04-22 19:24:42 UTC (rev 199890)
@@ -58,6 +58,77 @@
 {
 }
 
+#if USE(APPKIT)
+
+static NSString *webFallbackFontFamily(void)
+{
+    static NSString *webFallbackFontFamily = [[[NSFont systemFontOfSize:16.0f] familyName] retain];
+    return webFallbackFontFamily;
+}
+
+void FontPlatformData::setFallbackCGFont()
+{
+    if (cgFont())
+        return;
+
+    // Ack! Something very bad happened, like a corrupt font.
+    // Try looking for an alternate 'base' font for this renderer.
+
+    // Special case hack to use "Times New Roman" in place of "Times".
+    // "Times RO" is a common font whose family name is "Times".
+    // It overrides the normal "Times" family font.
+    // It also appears to have a corrupt regular variant.
+    NSString *fallbackFontFamily;
+    if ([[nsFont() familyName] isEqual:@"Times"])
+        fallbackFontFamily = @"Times New Roman";
+    else
+        fallbackFontFamily = webFallbackFontFamily();
+
+    // Try setting up the alternate font.
+    // This is a last ditch effort to use a substitute font when something has gone wrong.
+#if !ERROR_DISABLED
+    RetainPtr<NSFont> initialFont = nsFont();
+#endif
+    if (font())
+        setNSFont([[NSFontManager sharedFontManager] convertFont:nsFont() toFamily:fallbackFontFamily]);
+    else
+        setNSFont([NSFont fontWithName:fallbackFontFamily size:size()]);
+
+    if (cgFont())
+        return;
+
+    if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
+        // OK, couldn't setup Times New Roman as an alternate to Times, fallback
+        // on the system font. If this fails we have no alternative left.
+        setNSFont([[NSFontManager sharedFontManager] convertFont:nsFont() toFamily:webFallbackFontFamily()]);
+        if (cgFont())
+            return;
+
+        // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
+        LOG_ERROR("unable to initialize with font %@", initialFont.get());
+    } else {
+        // We tried the requested font and the system font. No joy. We have to give up.
+        LOG_ERROR("unable to initialize with font %@", initialFont.get());
+    }
+
+    // Report the problem.
+    LOG_ERROR("Corrupt font detected, using %@ in place of %@.", [nsFont() familyName], [initialFont.get() familyName]);
+
+    // If all else fails, try to set up using the system font.
+    // This is probably because Times and Times New Roman are both unavailable.
+    ASSERT(!cgFont());
+    setNSFont([NSFont systemFontOfSize:[nsFont() pointSize]]);
+    LOG_ERROR("failed to set up font, using system font %s", font());
+}
+
+#else
+
+void FontPlatformData::setFallbackCGFont()
+{
+}
+
+#endif
+
 void FontPlatformData::platformDataInit(const FontPlatformData& f)
 {
     m_font = f.m_font;

Modified: trunk/Source/WebCore/platform/graphics/freetype/FontPlatformData.h (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/freetype/FontPlatformData.h	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/freetype/FontPlatformData.h	2016-04-22 19:24:42 UTC (rev 199890)
@@ -72,7 +72,7 @@
 
     HarfBuzzFace* harfBuzzFace() const;
 
-    bool isFixedPitch();
+    bool isFixedPitch() const;
     float size() const { return m_size; }
     void setSize(float size) { m_size = size; }
     bool syntheticBold() const { return m_syntheticBold; }

Modified: trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -273,7 +273,7 @@
     return m_harfBuzzFace.get();
 }
 
-bool FontPlatformData::isFixedPitch()
+bool FontPlatformData::isFixedPitch() const
 {
     return m_fixedWidth;
 }

Modified: trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -113,6 +113,8 @@
     LOGFONT logfont;
     GetObject(font, sizeof(logfont), &logfont);
     m_cgFont = adoptCF(CGFontCreateWithPlatformFont(&logfont));
+    if (!m_useGDI)
+        m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
 }
 
 FontPlatformData::FontPlatformData(GDIObject<HFONT> hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI)
@@ -155,4 +157,8 @@
         && m_useGDI == other.m_useGDI;
 }
 
+void FontPlatformData::setFallbackCGFont()
+{
 }
+
+}

Modified: trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -54,6 +54,9 @@
 
     m_scaledFont = cairo_scaled_font_create(fontFace, &sizeMatrix, &ctm, fontOptions);
     cairo_font_face_destroy(fontFace);
+
+    if (!m_useGDI && m_size)
+        m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
 }
 
 FontPlatformData::FontPlatformData(GDIObject<HFONT> font, cairo_font_face_t* fontFace, float size, bool bold, bool oblique)

Modified: trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -86,7 +86,6 @@
         int faceLength = GetTextFace(dc, 0, 0);
         Vector<WCHAR> faceName(faceLength);
         GetTextFace(dc, faceLength, faceName.data());
-        m_platformData.setIsSystemFont(!wcscmp(faceName.data(), L"Lucida Grande"));
         SelectObject(dc, oldFont);
 
         fAscent = ascentConsideringMacAscentHack(faceName.data(), fAscent, fDescent);

Modified: trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp (199889 => 199890)


--- trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp	2016-04-22 19:22:54 UTC (rev 199889)
+++ trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp	2016-04-22 19:24:42 UTC (rev 199890)
@@ -46,7 +46,6 @@
     m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
     m_scriptCache = 0;
     m_scriptFontProperties = 0;
-    m_platformData.setIsSystemFont(false);
 
     if (m_platformData.useGDI())
        return initGDIFont();
@@ -55,7 +54,6 @@
         m_fontMetrics.reset();
         m_avgCharWidth = 0;
         m_maxCharWidth = 0;
-        m_platformData.setIsSystemFont(false);
         m_scriptCache = 0;
         m_scriptFontProperties = 0;
         return;
@@ -87,11 +85,6 @@
     }
     float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
 
-    int faceLength = ::GetTextFace(dc, 0, 0);
-    Vector<WCHAR> faceName(faceLength);
-    ::GetTextFace(dc, faceLength, faceName.data());
-    m_platformData.setIsSystemFont(!wcscmp(faceName.data(), L"Lucida Grande"));
-
     m_fontMetrics.setAscent(ascent);
     m_fontMetrics.setDescent(descent);
     m_fontMetrics.setLineGap(lineGap);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to