Changeset 205694 in webkit


Ignore:
Timestamp:
Sep 8, 2016 10:11:25 PM (8 years ago)
Author:
Yusuke Suzuki
Message:

[WTF] HashTable's rehash is not compatible to Ref<T> and ASan
https://bugs.webkit.org/show_bug.cgi?id=161763

Reviewed by Mark Lam.

Source/WebCore:

Include wtf/text/StringHash.h to avoid linking errors in EFL port.

  • loader/ResourceLoadStatistics.h:

Source/WTF:

If we move an object, the location which the moved object used should not be touched anymore.
HashTable::rehash performs WTFMove for the object that resides in the old table.
However, after moving it, we accidentally touch this location by using !isEmptyOrDeletedBucket(table[i])
in HashTable::deallocateTable. And it causes ASan crashing if we use Ref<> for HashTable's key or value.

In this patch, we call the destructor right after moving the object. And HashTable::rehash just calls
fastFree since all the objects in the old table are already moved and destructed.
And we also change HashTable::deallocate to destruct only live objects. Calling destructors for empty objects
is meaningless. And according to the Ref<>'s comment, empty object is not designed to be destructed.

  • wtf/HashTable.h:

(WTF::KeyTraits>::deallocateTable):

Tools:

Add tests that inserts many Ref<>s. It incurs HashTable::rehash, and we can ensure
that ASan crash does not occur with this patch.

  • TestWebKitAPI/Tests/WTF/HashMap.cpp:

(TestWebKitAPI::TEST):

  • TestWebKitAPI/Tests/WTF/HashSet.cpp:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r205683 r205694  
     12016-09-08  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [WTF] HashTable's rehash is not compatible to Ref<T> and ASan
     4        https://bugs.webkit.org/show_bug.cgi?id=161763
     5
     6        Reviewed by Mark Lam.
     7
     8        If we move an object, the location which the moved object used should not be touched anymore.
     9        HashTable::rehash performs WTFMove for the object that resides in the old table.
     10        However, after moving it, we accidentally touch this location by using `!isEmptyOrDeletedBucket(table[i])`
     11        in HashTable::deallocateTable. And it causes ASan crashing if we use Ref<> for HashTable's key or value.
     12
     13        In this patch, we call the destructor right after moving the object. And HashTable::rehash just calls
     14        fastFree since all the objects in the old table are already moved and destructed.
     15        And we also change HashTable::deallocate to destruct only live objects. Calling destructors for empty objects
     16        is meaningless. And according to the Ref<>'s comment, empty object is not designed to be destructed.
     17
     18        * wtf/HashTable.h:
     19        (WTF::KeyTraits>::deallocateTable):
     20
    1212016-09-08  Filip Pizlo  <fpizlo@apple.com>
    222
  • trunk/Source/WTF/wtf/HashTable.h

    r204519 r205694  
    11541154    {
    11551155        for (unsigned i = 0; i < size; ++i) {
    1156             if (!isDeletedBucket(table[i]))
     1156            if (!isEmptyOrDeletedBucket(table[i]))
    11571157                table[i].~ValueType();
    11581158        }
     
    12041204
    12051205            Value* reinsertedEntry = reinsert(WTFMove(oldTable[i]));
     1206            oldTable[i].~ValueType();
    12061207            if (std::addressof(oldTable[i]) == entry) {
    12071208                ASSERT(!newEntry);
     
    12121213        m_deletedCount = 0;
    12131214
    1214         deallocateTable(oldTable, oldTableSize);
     1215        fastFree(oldTable);
    12151216
    12161217        internalCheckTableConsistency();
  • trunk/Source/WebCore/ChangeLog

    r205691 r205694  
     12016-09-08  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [WTF] HashTable's rehash is not compatible to Ref<T> and ASan
     4        https://bugs.webkit.org/show_bug.cgi?id=161763
     5
     6        Reviewed by Mark Lam.
     7
     8        Include wtf/text/StringHash.h to avoid linking errors in EFL port.
     9
     10        * loader/ResourceLoadStatistics.h:
     11
    1122016-09-08  Chris Dumez  <cdumez@apple.com>
    213
  • trunk/Source/WebCore/loader/ResourceLoadStatistics.h

    r198055 r205694  
    2828
    2929#include <wtf/HashCountedSet.h>
     30#include <wtf/text/StringHash.h>
    3031#include <wtf/text/WTFString.h>
    3132
  • trunk/Tools/ChangeLog

    r205684 r205694  
     12016-09-08  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [WTF] HashTable's rehash is not compatible to Ref<T> and ASan
     4        https://bugs.webkit.org/show_bug.cgi?id=161763
     5
     6        Reviewed by Mark Lam.
     7
     8        Add tests that inserts many Ref<>s. It incurs HashTable::rehash, and we can ensure
     9        that ASan crash does not occur with this patch.
     10
     11        * TestWebKitAPI/Tests/WTF/HashMap.cpp:
     12        (TestWebKitAPI::TEST):
     13        * TestWebKitAPI/Tests/WTF/HashSet.cpp:
     14        (TestWebKitAPI::TEST):
     15
    1162016-09-08  Alex Christensen  <achristensen@webkit.org>
    217
  • trunk/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp

    r204519 r205694  
    790790
    791791    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
     792
     793    {
     794        HashMap<Ref<RefLogger>, int> map;
     795        for (int i = 0; i < 64; ++i) {
     796            Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
     797            auto* pointer = ref.ptr();
     798            map.add(WTFMove(ref), i + 1);
     799            ASSERT_TRUE(map.contains(pointer));
     800        }
     801    }
     802
     803    ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
    792804}
    793805
     
    891903
    892904    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
     905
     906    {
     907        HashMap<int, Ref<RefLogger>> map;
     908        for (int i = 0; i < 64; ++i) {
     909            Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
     910            map.add(i + 1, WTFMove(ref));
     911            ASSERT_TRUE(map.contains(i + 1));
     912        }
     913    }
     914
     915    ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
    893916}
    894917
  • trunk/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp

    r204519 r205694  
    429429
    430430    ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
     431
     432    {
     433        HashSet<Ref<RefLogger>> set;
     434        for (int i = 0; i < 64; ++i) {
     435            Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
     436            auto* pointer = ref.ptr();
     437            set.add(WTFMove(ref));
     438            ASSERT_TRUE(set.contains(pointer));
     439        }
     440    }
     441    ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
    431442}
    432443
Note: See TracChangeset for help on using the changeset viewer.