Title: [98268] trunk/Source/_javascript_Core
Revision
98268
Author
[email protected]
Date
2011-10-24 12:41:29 -0700 (Mon, 24 Oct 2011)

Log Message

BitVector isInline check could fail
https://bugs.webkit.org/show_bug.cgi?id=70691

Patch by Yuqiang Xian <[email protected]> on 2011-10-24
Reviewed by Geoffrey Garen.

Current BitVector uses the highest bit of m_bitsOrPointer to indicate
whether it's an inlined bit set or a pointer to an outOfLine bit set.
This check may fail in case the pointer also has the highest bit set,
which is surely possible on IA32 (Linux).
In this case the check failure can result in unexpected behaviors,
for example if the BitVector is incorrectly determined as having an
inlined bit set, then setting a bit exceeding maxInlineBits will wrongly
modify the memory adjacent to the BitVector object.
This fix is to use the lowest bit of m_bitsOrPointer to indicate inline
or outofline, based on the assumption that the pointer to OutOfLineBits
should be 4 or 8 byte aligned.
We could mark the lowest bit (bit 0) with 1 for inlined bit set,
and bits 1~bitsInPointer are used for bit set/test.
In this case we need do one bit more shift for bit set/test.

* wtf/BitVector.cpp:
(WTF::BitVector::resizeOutOfLine):
* wtf/BitVector.h:
(WTF::BitVector::quickGet):
(WTF::BitVector::quickSet):
(WTF::BitVector::quickClear):
(WTF::BitVector::makeInlineBits):
(WTF::BitVector::isInline):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (98267 => 98268)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-24 19:40:54 UTC (rev 98267)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-24 19:41:29 UTC (rev 98268)
@@ -1,3 +1,34 @@
+2011-10-24  Yuqiang Xian  <[email protected]>
+
+        BitVector isInline check could fail
+        https://bugs.webkit.org/show_bug.cgi?id=70691
+
+        Reviewed by Geoffrey Garen.
+
+        Current BitVector uses the highest bit of m_bitsOrPointer to indicate
+        whether it's an inlined bit set or a pointer to an outOfLine bit set.
+        This check may fail in case the pointer also has the highest bit set,
+        which is surely possible on IA32 (Linux).
+        In this case the check failure can result in unexpected behaviors,
+        for example if the BitVector is incorrectly determined as having an
+        inlined bit set, then setting a bit exceeding maxInlineBits will wrongly
+        modify the memory adjacent to the BitVector object.
+        This fix is to use the lowest bit of m_bitsOrPointer to indicate inline
+        or outofline, based on the assumption that the pointer to OutOfLineBits
+        should be 4 or 8 byte aligned.
+        We could mark the lowest bit (bit 0) with 1 for inlined bit set,
+        and bits 1~bitsInPointer are used for bit set/test.
+        In this case we need do one bit more shift for bit set/test.
+
+        * wtf/BitVector.cpp:
+        (WTF::BitVector::resizeOutOfLine):
+        * wtf/BitVector.h:
+        (WTF::BitVector::quickGet):
+        (WTF::BitVector::quickSet):
+        (WTF::BitVector::quickClear):
+        (WTF::BitVector::makeInlineBits):
+        (WTF::BitVector::isInline):
+
 2011-10-24  Mark Hahnenberg  <[email protected]>
 
         Rename static getOwnPropertySlot to getOwnPropertySlotByIndex

Modified: trunk/Source/_javascript_Core/wtf/BitVector.cpp (98267 => 98268)


--- trunk/Source/_javascript_Core/wtf/BitVector.cpp	2011-10-24 19:40:54 UTC (rev 98267)
+++ trunk/Source/_javascript_Core/wtf/BitVector.cpp	2011-10-24 19:41:29 UTC (rev 98268)
@@ -91,7 +91,7 @@
     OutOfLineBits* newOutOfLineBits = OutOfLineBits::create(numBits);
     if (isInline()) {
         // Make sure that all of the bits are zero in case we do a no-op resize.
-        *newOutOfLineBits->bits() = m_bitsOrPointer & ~(static_cast<uintptr_t>(1) << maxInlineBits());
+        *newOutOfLineBits->bits() = m_bitsOrPointer & ~(static_cast<uintptr_t>(1));
     } else {
         if (numBits > size()) {
             size_t oldNumWords = outOfLineBits()->numWords();
@@ -103,6 +103,7 @@
         OutOfLineBits::destroy(outOfLineBits());
     }
     m_bitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits);
+    ASSERT(!isInline());
 }
 
 #ifndef NDEBUG

Modified: trunk/Source/_javascript_Core/wtf/BitVector.h (98267 => 98268)


--- trunk/Source/_javascript_Core/wtf/BitVector.h	2011-10-24 19:40:54 UTC (rev 98267)
+++ trunk/Source/_javascript_Core/wtf/BitVector.h	2011-10-24 19:41:29 UTC (rev 98268)
@@ -114,19 +114,19 @@
     bool quickGet(size_t bit) const
     {
         ASSERT(bit < size());
-        return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))));
+        return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1)));
     }
     
     void quickSet(size_t bit)
     {
         ASSERT(bit < size());
-        bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)));
+        bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1));
     }
     
     void quickClear(size_t bit)
     {
         ASSERT(bit < size());
-        bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)));
+        bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1));
     }
     
     void quickSet(size_t bit, bool value)
@@ -187,8 +187,8 @@
     
     static uintptr_t makeInlineBits(uintptr_t bits)
     {
-        ASSERT(!(bits & (static_cast<uintptr_t>(1) << maxInlineBits())));
-        return bits | (static_cast<uintptr_t>(1) << maxInlineBits());
+        ASSERT(!(bits & static_cast<uintptr_t>(1)));
+        return bits | static_cast<uintptr_t>(1);
     }
     
     class OutOfLineBits {
@@ -211,7 +211,7 @@
         size_t m_numBits;
     };
     
-    bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); }
+    bool isInline() const { return m_bitsOrPointer & static_cast<uintptr_t>(1); }
     
     const OutOfLineBits* outOfLineBits() const { return bitwise_cast<const OutOfLineBits*>(m_bitsOrPointer); }
     OutOfLineBits* outOfLineBits() { return bitwise_cast<OutOfLineBits*>(m_bitsOrPointer); }
@@ -232,7 +232,10 @@
             return &m_bitsOrPointer;
         return outOfLineBits()->bits();
     }
-    
+
+    // The low bit of m_bitsOrPointer is a flag indicating whether this field is
+    // inline bits or a pointer to out of line bits. If the flag is set, the field
+    // is inline bits. This works because the low bit in a pointer is always unset.
     uintptr_t m_bitsOrPointer;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to