Changeset 98268 in webkit


Ignore:
Timestamp:
Oct 24, 2011 12:41:29 PM (12 years ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Yuqiang Xian <yuqiang.xian@intel.com> 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):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r98261 r98268  
     12011-10-24  Yuqiang Xian  <yuqiang.xian@intel.com>
     2
     3        BitVector isInline check could fail
     4        https://bugs.webkit.org/show_bug.cgi?id=70691
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Current BitVector uses the highest bit of m_bitsOrPointer to indicate
     9        whether it's an inlined bit set or a pointer to an outOfLine bit set.
     10        This check may fail in case the pointer also has the highest bit set,
     11        which is surely possible on IA32 (Linux).
     12        In this case the check failure can result in unexpected behaviors,
     13        for example if the BitVector is incorrectly determined as having an
     14        inlined bit set, then setting a bit exceeding maxInlineBits will wrongly
     15        modify the memory adjacent to the BitVector object.
     16        This fix is to use the lowest bit of m_bitsOrPointer to indicate inline
     17        or outofline, based on the assumption that the pointer to OutOfLineBits
     18        should be 4 or 8 byte aligned.
     19        We could mark the lowest bit (bit 0) with 1 for inlined bit set,
     20        and bits 1~bitsInPointer are used for bit set/test.
     21        In this case we need do one bit more shift for bit set/test.
     22
     23        * wtf/BitVector.cpp:
     24        (WTF::BitVector::resizeOutOfLine):
     25        * wtf/BitVector.h:
     26        (WTF::BitVector::quickGet):
     27        (WTF::BitVector::quickSet):
     28        (WTF::BitVector::quickClear):
     29        (WTF::BitVector::makeInlineBits):
     30        (WTF::BitVector::isInline):
     31
    1322011-10-24  Mark Hahnenberg  <mhahnenberg@apple.com>
    233
  • trunk/Source/JavaScriptCore/wtf/BitVector.cpp

    r97197 r98268  
    9292    if (isInline()) {
    9393        // Make sure that all of the bits are zero in case we do a no-op resize.
    94         *newOutOfLineBits->bits() = m_bitsOrPointer & ~(static_cast<uintptr_t>(1) << maxInlineBits());
     94        *newOutOfLineBits->bits() = m_bitsOrPointer & ~(static_cast<uintptr_t>(1));
    9595    } else {
    9696        if (numBits > size()) {
     
    104104    }
    105105    m_bitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits);
     106    ASSERT(!isInline());
    106107}
    107108
  • trunk/Source/JavaScriptCore/wtf/BitVector.h

    r97211 r98268  
    115115    {
    116116        ASSERT(bit < size());
    117         return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))));
     117        return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1)));
    118118    }
    119119   
     
    121121    {
    122122        ASSERT(bit < size());
    123         bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)));
     123        bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1));
    124124    }
    125125   
     
    127127    {
    128128        ASSERT(bit < size());
    129         bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)));
     129        bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << ((bit & (bitsInPointer() - 1)) + 1));
    130130    }
    131131   
     
    188188    static uintptr_t makeInlineBits(uintptr_t bits)
    189189    {
    190         ASSERT(!(bits & (static_cast<uintptr_t>(1) << maxInlineBits())));
    191         return bits | (static_cast<uintptr_t>(1) << maxInlineBits());
     190        ASSERT(!(bits & static_cast<uintptr_t>(1)));
     191        return bits | static_cast<uintptr_t>(1);
    192192    }
    193193   
     
    212212    };
    213213   
    214     bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); }
     214    bool isInline() const { return m_bitsOrPointer & static_cast<uintptr_t>(1); }
    215215   
    216216    const OutOfLineBits* outOfLineBits() const { return bitwise_cast<const OutOfLineBits*>(m_bitsOrPointer); }
     
    233233        return outOfLineBits()->bits();
    234234    }
    235    
     235
     236    // The low bit of m_bitsOrPointer is a flag indicating whether this field is
     237    // inline bits or a pointer to out of line bits. If the flag is set, the field
     238    // is inline bits. This works because the low bit in a pointer is always unset.
    236239    uintptr_t m_bitsOrPointer;
    237240};
Note: See TracChangeset for help on using the changeset viewer.