Changeset 199890 in webkit


Ignore:
Timestamp:
Apr 22, 2016 12:24:42 PM (8 years ago)
Author:
Chris Dumez
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):

Location:
trunk/Source/WebCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r199889 r199890  
     12016-04-22  Chris Dumez  <cdumez@apple.com>
     2
     3        Crash under FontCache::purgeInactiveFontData()
     4        https://bugs.webkit.org/show_bug.cgi?id=156822
     5        <rdar://problem/25373970>
     6
     7        Reviewed by Darin Adler.
     8
     9        In some rare cases, the Font constructor would mutate the FontPlatformData
     10        that is being passed in. This is an issue because because our FontCache
     11        uses the FontPlatformData as key for the cached fonts. This could lead to
     12        crashes because the WTFMove() in FontCache::purgeInactiveFontData() would
     13        nullify values in our HashMap but we would then fail to remove them from
     14        the HashMap (because the key did not match). We would then reference the
     15        null font when looping again when doing font->hasOneRef().
     16
     17        This patch marks Font::m_platformData member as const to avoid such issues
     18        in the future and moves the code altering the FontPlatformData from the
     19        Font constructor into the FontPlatformData constructor. The purpose of
     20        that code was to initialize FontPlatformData::m_cgFont in case the CGFont
     21        passed in the constructor was null.
     22
     23        * platform/graphics/Font.h:
     24        * platform/graphics/FontCache.cpp:
     25        (WebCore::FontCache::fontForPlatformData):
     26        (WebCore::FontCache::purgeInactiveFontData):
     27        * platform/graphics/FontPlatformData.cpp:
     28        (WebCore::FontPlatformData::FontPlatformData):
     29        * platform/graphics/FontPlatformData.h:
     30        * platform/graphics/cocoa/FontCocoa.mm:
     31        (WebCore::webFallbackFontFamily): Deleted.
     32        (WebCore::Font::platformInit): Deleted.
     33        * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
     34        (WebCore::webFallbackFontFamily):
     35        (WebCore::FontPlatformData::setFallbackCGFont):
     36        * platform/graphics/win/FontPlatformDataCGWin.cpp:
     37        (WebCore::FontPlatformData::setFallbackCGFont):
     38
    1392016-04-22  Chris Dumez  <cdumez@apple.com>
    240
  • trunk/Source/WebCore/platform/graphics/Font.h

    r198850 r199890  
    230230    float m_avgCharWidth;
    231231
    232     FontPlatformData m_platformData;
     232    const FontPlatformData m_platformData;
    233233
    234234    mutable RefPtr<GlyphPage> m_glyphPageZero;
  • trunk/Source/WebCore/platform/graphics/FontCache.cpp

    r196969 r199890  
    397397        addResult.iterator->value = Font::create(platformData);
    398398
     399    ASSERT(addResult.iterator->value->platformData() == platformData);
     400
    399401    return *addResult.iterator->value;
    400402}
     
    436438        if (fontsToDelete.isEmpty())
    437439            break;
    438         for (auto& font : fontsToDelete)
    439             cachedFonts().remove(font->platformData());
     440        for (auto& font : fontsToDelete) {
     441            bool success = cachedFonts().remove(font->platformData());
     442            ASSERT_UNUSED(success, success);
     443        }
    440444    };
    441445
  • trunk/Source/WebCore/platform/graphics/FontPlatformData.cpp

    r192895 r199890  
    5959{
    6060    m_cgFont = cgFont;
     61    if (!m_cgFont)
     62        setFallbackCGFont();
    6163}
    6264#endif
  • trunk/Source/WebCore/platform/graphics/FontPlatformData.h

    r192917 r199890  
    217217    void platformDataInit(HFONT, float size, HDC, WCHAR* faceName);
    218218#endif
     219#if USE(CG)
     220    void setFallbackCGFont();
     221#endif
    219222
    220223public:
  • trunk/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm

    r199150 r199890  
    8080}
    8181
    82 #if USE(APPKIT)
    83 static NSString *webFallbackFontFamily(void)
    84 {
    85     static NSString *webFallbackFontFamily = [[[NSFont systemFontOfSize:16.0f] familyName] retain];
    86     return webFallbackFontFamily;
    87 }
    88 #else
     82#if !USE(APPKIT)
    8983bool fontFamilyShouldNotBeUsedForArabic(CFStringRef fontFamilyName)
    9084{
     
    10498#if USE(APPKIT)
    10599    m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
    106 
    107     bool failedSetup = false;
    108     if (!platformData().cgFont()) {
    109         // Ack! Something very bad happened, like a corrupt font.
    110         // Try looking for an alternate 'base' font for this renderer.
    111 
    112         // Special case hack to use "Times New Roman" in place of "Times".
    113         // "Times RO" is a common font whose family name is "Times".
    114         // It overrides the normal "Times" family font.
    115         // It also appears to have a corrupt regular variant.
    116         NSString *fallbackFontFamily;
    117         if ([[m_platformData.nsFont() familyName] isEqual:@"Times"])
    118             fallbackFontFamily = @"Times New Roman";
    119         else
    120             fallbackFontFamily = webFallbackFontFamily();
    121        
    122         // Try setting up the alternate font.
    123         // This is a last ditch effort to use a substitute font when something has gone wrong.
    124 #if !ERROR_DISABLED
    125         RetainPtr<NSFont> initialFont = m_platformData.nsFont();
    126 #endif
    127         if (m_platformData.font())
    128             m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:fallbackFontFamily]);
    129         else
    130             m_platformData.setNSFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
    131         if (!platformData().cgFont()) {
    132             if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
    133                 // OK, couldn't setup Times New Roman as an alternate to Times, fallback
    134                 // on the system font.  If this fails we have no alternative left.
    135                 m_platformData.setNSFont([[NSFontManager sharedFontManager] convertFont:m_platformData.nsFont() toFamily:webFallbackFontFamily()]);
    136                 if (!platformData().cgFont()) {
    137                     // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
    138                     LOG_ERROR("unable to initialize with font %@", initialFont.get());
    139                     failedSetup = true;
    140                 }
    141             } else {
    142                 // We tried the requested font and the system font. No joy. We have to give up.
    143                 LOG_ERROR("unable to initialize with font %@", initialFont.get());
    144                 failedSetup = true;
    145             }
    146         }
    147 
    148         // Report the problem.
    149         LOG_ERROR("Corrupt font detected, using %@ in place of %@.",
    150             [m_platformData.nsFont() familyName], [initialFont.get() familyName]);
    151     }
    152 
    153     // If all else fails, try to set up using the system font.
    154     // This is probably because Times and Times New Roman are both unavailable.
    155     if (failedSetup) {
    156         m_platformData.setNSFont([NSFont systemFontOfSize:[m_platformData.nsFont() pointSize]]);
    157         LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
    158     }
    159100
    160101#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100
  • trunk/Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm

    r194656 r199890  
    5858{
    5959}
     60
     61#if USE(APPKIT)
     62
     63static NSString *webFallbackFontFamily(void)
     64{
     65    static NSString *webFallbackFontFamily = [[[NSFont systemFontOfSize:16.0f] familyName] retain];
     66    return webFallbackFontFamily;
     67}
     68
     69void FontPlatformData::setFallbackCGFont()
     70{
     71    if (cgFont())
     72        return;
     73
     74    // Ack! Something very bad happened, like a corrupt font.
     75    // Try looking for an alternate 'base' font for this renderer.
     76
     77    // Special case hack to use "Times New Roman" in place of "Times".
     78    // "Times RO" is a common font whose family name is "Times".
     79    // It overrides the normal "Times" family font.
     80    // It also appears to have a corrupt regular variant.
     81    NSString *fallbackFontFamily;
     82    if ([[nsFont() familyName] isEqual:@"Times"])
     83        fallbackFontFamily = @"Times New Roman";
     84    else
     85        fallbackFontFamily = webFallbackFontFamily();
     86
     87    // Try setting up the alternate font.
     88    // This is a last ditch effort to use a substitute font when something has gone wrong.
     89#if !ERROR_DISABLED
     90    RetainPtr<NSFont> initialFont = nsFont();
     91#endif
     92    if (font())
     93        setNSFont([[NSFontManager sharedFontManager] convertFont:nsFont() toFamily:fallbackFontFamily]);
     94    else
     95        setNSFont([NSFont fontWithName:fallbackFontFamily size:size()]);
     96
     97    if (cgFont())
     98        return;
     99
     100    if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
     101        // OK, couldn't setup Times New Roman as an alternate to Times, fallback
     102        // on the system font. If this fails we have no alternative left.
     103        setNSFont([[NSFontManager sharedFontManager] convertFont:nsFont() toFamily:webFallbackFontFamily()]);
     104        if (cgFont())
     105            return;
     106
     107        // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
     108        LOG_ERROR("unable to initialize with font %@", initialFont.get());
     109    } else {
     110        // We tried the requested font and the system font. No joy. We have to give up.
     111        LOG_ERROR("unable to initialize with font %@", initialFont.get());
     112    }
     113
     114    // Report the problem.
     115    LOG_ERROR("Corrupt font detected, using %@ in place of %@.", [nsFont() familyName], [initialFont.get() familyName]);
     116
     117    // If all else fails, try to set up using the system font.
     118    // This is probably because Times and Times New Roman are both unavailable.
     119    ASSERT(!cgFont());
     120    setNSFont([NSFont systemFontOfSize:[nsFont() pointSize]]);
     121    LOG_ERROR("failed to set up font, using system font %s", font());
     122}
     123
     124#else
     125
     126void FontPlatformData::setFallbackCGFont()
     127{
     128}
     129
     130#endif
    60131
    61132void FontPlatformData::platformDataInit(const FontPlatformData& f)
  • trunk/Source/WebCore/platform/graphics/freetype/FontPlatformData.h

    r188130 r199890  
    7373    HarfBuzzFace* harfBuzzFace() const;
    7474
    75     bool isFixedPitch();
     75    bool isFixedPitch() const;
    7676    float size() const { return m_size; }
    7777    void setSize(float size) { m_size = size; }
  • trunk/Source/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp

    r190557 r199890  
    274274}
    275275
    276 bool FontPlatformData::isFixedPitch()
     276bool FontPlatformData::isFixedPitch() const
    277277{
    278278    return m_fixedWidth;
  • trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp

    r194496 r199890  
    114114    GetObject(font, sizeof(logfont), &logfont);
    115115    m_cgFont = adoptCF(CGFontCreateWithPlatformFont(&logfont));
     116    if (!m_useGDI)
     117        m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
    116118}
    117119
     
    156158}
    157159
     160void FontPlatformData::setFallbackCGFont()
     161{
    158162}
     163
     164}
  • trunk/Source/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp

    r194496 r199890  
    5555    m_scaledFont = cairo_scaled_font_create(fontFace, &sizeMatrix, &ctm, fontOptions);
    5656    cairo_font_face_destroy(fontFace);
     57
     58    if (!m_useGDI && m_size)
     59        m_isSystemFont = !wcscmp(faceName, L"Lucida Grande");
    5760}
    5861
  • trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp

    r192917 r199890  
    8787        Vector<WCHAR> faceName(faceLength);
    8888        GetTextFace(dc, faceLength, faceName.data());
    89         m_platformData.setIsSystemFont(!wcscmp(faceName.data(), L"Lucida Grande"));
    9089        SelectObject(dc, oldFont);
    9190
  • trunk/Source/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp

    r192943 r199890  
    4747    m_scriptCache = 0;
    4848    m_scriptFontProperties = 0;
    49     m_platformData.setIsSystemFont(false);
    5049
    5150    if (m_platformData.useGDI())
     
    5655        m_avgCharWidth = 0;
    5756        m_maxCharWidth = 0;
    58         m_platformData.setIsSystemFont(false);
    5957        m_scriptCache = 0;
    6058        m_scriptFontProperties = 0;
     
    8785    }
    8886    float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
    89 
    90     int faceLength = ::GetTextFace(dc, 0, 0);
    91     Vector<WCHAR> faceName(faceLength);
    92     ::GetTextFace(dc, faceLength, faceName.data());
    93     m_platformData.setIsSystemFont(!wcscmp(faceName.data(), L"Lucida Grande"));
    9487
    9588    m_fontMetrics.setAscent(ascent);
Note: See TracChangeset for help on using the changeset viewer.