⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179702 in webkit


Ignore:
Timestamp:
Feb 5, 2015, 1:29:19 PM (12 years ago)
Author:
Chris Dumez
Message:

Free memory read under MemoryCache::pruneLiveResourcesToSize()
​https://bugs.webkit.org/show_bug.cgi?id=141292
<rdar://problem/19725522>

Reviewed by Antti Koivisto.

In MemoryCache::pruneLiveResourcesToSize(), we were iterating over the
m_liveDecodedResources ListHashSet and possibly calling
CachedResource::destroyDecodedData() on the current value. Doing so
would cause a call to ListHashSet::remove() to remove the value pointed
by the current iterator, thus invalidating our iterator.

In this patch, we increment the ListHashSet iterator *before* calling
CachedResource::destroyDecodedData(), while the current iterator is
still valid. Note that this is safe because unlike iteration of most
WTF Hash data structures, iteration is guaranteed safe against mutation
of the ListHashSet, except for removal of the item currently pointed to
by a given iterator.

Test: http/tests/cache/memory-cache-pruning.html

  • loader/cache/MemoryCache.cpp:

(WebCore::MemoryCache::pruneLiveResourcesToSize):

Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r179699 r179702  
     12015-02-05  Chris Dumez  <cdumez@apple.com>
     2
     3        Free memory read under MemoryCache::pruneLiveResourcesToSize()
     4        https://bugs.webkit.org/show_bug.cgi?id=141292
     5        <rdar://problem/19725522>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        In MemoryCache::pruneLiveResourcesToSize(), we were iterating over the
     10        m_liveDecodedResources ListHashSet and possibly calling
     11        CachedResource::destroyDecodedData() on the current value. Doing so
     12        would cause a call to ListHashSet::remove() to remove the value pointed
     13        by the current iterator, thus invalidating our iterator.
     14
     15        In this patch, we increment the ListHashSet iterator *before* calling
     16        CachedResource::destroyDecodedData(), while the current iterator is
     17        still valid. Note that this is safe because unlike iteration of most
     18        WTF Hash data structures, iteration is guaranteed safe against mutation
     19        of the ListHashSet, except for removal of the item currently pointed to
     20        by a given iterator.
     21
     22        Test: http/tests/cache/memory-cache-pruning.html
     23
     24        * loader/cache/MemoryCache.cpp:
     25        (WebCore::MemoryCache::pruneLiveResourcesToSize):
     26
    1272015-02-05  Jer Noble  <jer.noble@apple.com>
    228
  • trunk/Source/WebCore/WebCore.exp.in

    r179604 r179702  
    198198__ZN7WebCore11MemoryCache19getOriginsWithCacheERN3WTF7HashSetINS1_6RefPtrINS_14SecurityOriginEEENS_18SecurityOriginHashENS1_10HashTraitsIS5_EEEE
    199199__ZN7WebCore11MemoryCache20removeImageFromCacheERKNS_3URLERKN3WTF6StringE
     200__ZN7WebCore11MemoryCache24pruneDeadResourcesToSizeEj
     201__ZN7WebCore11MemoryCache24pruneLiveResourcesToSizeEjb
    200202__ZN7WebCore11MemoryCache25removeResourcesWithOriginERNS_14SecurityOriginE
    201203__ZN7WebCore11MemoryCache9singletonEv
  • trunk/Source/WebCore/loader/cache/MemoryCache.cpp

    r179489 r179702  
    301301    // greater than the current->m_lastDecodedAccessTime.
    302302    // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209
    303     for (auto* current : m_liveDecodedResources) {
     303    auto it = m_liveDecodedResources.begin();
     304    while (it != m_liveDecodedResources.end()) {
     305        auto* current = *it;
     306
     307        // Increment the iterator now because the call to destroyDecodedData() below
     308        // may cause a call to ListHashSet::remove() and invalidate the current
     309        // iterator. Note that this is safe because unlike iteration of most
     310        // WTF Hash data structures, iteration is guaranteed safe against mutation
     311        // of the ListHashSet, except for removal of the item currently pointed to
     312        // by a given iterator.
     313        ++it;
     314
    304315        ASSERT(current->hasClients());
    305316        if (current->isLoaded() && current->decodedSize()) {
    … …  
    312323                continue;
    313324
    314             // Destroy our decoded data. This will remove us from
    315             // m_liveDecodedResources, and possibly move us to a different LRU
    316             // list in m_allResources.
     325            // Destroy our decoded data. This will remove us from m_liveDecodedResources, and possibly move us
     326            // to a different LRU list in m_allResources.
    317327            current->destroyDecodedData();
    318328
  • trunk/Source/WebCore/loader/cache/MemoryCache.h

    r179489 r179702  
    6363    WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
    6464    friend NeverDestroyed<MemoryCache>;
    65 
     65    friend class Internals;
    6666public:
    6767    struct TypeStatistic {
    … …  
    118118   
    119119    void prune();
     120    unsigned size() const { return m_liveSize + m_deadSize; }
    120121
    121122    void setDeadDecodedDataDeletionInterval(std::chrono::milliseconds interval) { m_deadDecodedDataDeletionInterval = interval; }
  • trunk/Source/WebCore/testing/Internals.cpp

    r179489 r179702  
    410410}
    411411
     412void Internals::pruneMemoryCacheToSize(unsigned size)
     413{
     414    MemoryCache::singleton().pruneDeadResourcesToSize(size);
     415    MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
     416}
     417
     418unsigned Internals::memoryCacheSize() const
     419{
     420    return MemoryCache::singleton().size();
     421}
     422
    412423Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
    413424{
  • trunk/Source/WebCore/testing/Internals.h

    r178820 r179702  
    8585    bool isLoadingFromMemoryCache(const String& url);
    8686    String xhrResponseSource(XMLHttpRequest*);
     87
    8788    void clearMemoryCache();
     89    void pruneMemoryCacheToSize(unsigned size);
     90    unsigned memoryCacheSize() const;
    8891
    8992    PassRefPtr<CSSComputedStyleDeclaration> computedStyleIncludingVisitedInfo(Node*, ExceptionCode&) const;
  • trunk/Source/WebCore/testing/Internals.idl

    r178820 r179702  
    4545    DOMString xhrResponseSource(XMLHttpRequest xhr);
    4646    void clearMemoryCache();
     47    void pruneMemoryCacheToSize(long size);
     48    long memoryCacheSize();
    4749
    4850    [RaisesException] CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);
Note: See TracChangeset for help on using the changeset viewer.