Ignore:
Timestamp:
Dec 1, 2008, 5:57:56 PM (16 years ago)
Author:
[email protected]
Message:

2008-12-01 Cameron Zwarich <[email protected]>

Reviewed by Oliver Hunt.

Bug 20340: SegmentedVector segment allocations can lead to unsafe use of temporary registers
<https://bugs.webkit.org/show_bug.cgi?id=20340>

SegmentedVector currently frees segments and reallocates them when used
as a stack. This can lead to unsafe use of pointers into freed segments.

In order to fix this problem, SegmentedVector will be changed to only
grow and never shrink. Also, rename the reserveCapacity() member
function to grow() to match the actual usage in BytecodeGenerator, where
this function is used to allocate a group of registers at once, rather
than merely saving space for them.

  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): Use grow() instead of reserveCapacity().
  • bytecompiler/SegmentedVector.h: (JSC::SegmentedVector::SegmentedVector): (JSC::SegmentedVector::last): (JSC::SegmentedVector::append): (JSC::SegmentedVector::removeLast): (JSC::SegmentedVector::grow): Renamed from reserveCapacity(). (JSC::SegmentedVector::clear):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/bytecompiler/SegmentedVector.h

    r38856 r38887  
    3838        SegmentedVector()
    3939            : m_size(0)
     40            , m_currentSegmentIndex(0)
    4041        {
    4142            m_segments.append(&m_inlineSegment);
     
    5152        {
    5253            ASSERT(m_size);
    53             return m_segments.last()->last();
     54            return m_segments[m_currentSegmentIndex]->last();
    5455        }
    5556
    5657        template <typename U> void append(const U& value)
    5758        {
    58             if (!(m_size % SegmentSize) && m_size)
    59                 m_segments.append(new Segment);
    60             m_segments.last()->uncheckedAppend(value);
     59            if (!(m_size % SegmentSize) && m_size) {
     60                if (m_currentSegmentIndex == m_segments.size() - 1)
     61                    m_segments.append(new Segment);
     62                m_currentSegmentIndex++;
     63            }
     64            m_segments[m_currentSegmentIndex]->uncheckedAppend(value);
    6165            m_size++;
    6266        }
     
    6670            ASSERT(m_size);
    6771            m_size--;
    68             m_segments.last()->removeLast();
    69             if (!(m_size % SegmentSize) && m_size >= SegmentSize) {
    70                 delete m_segments.last();
    71                 m_segments.removeLast();
    72             }
     72            m_segments[m_currentSegmentIndex]->removeLast();
     73            if (!(m_size % SegmentSize) && m_size >= SegmentSize)
     74                m_currentSegmentIndex--;
    7375        }
    7476
     
    8688        }
    8789
    88         void reserveCapacity(size_t newCapacity)
     90        void grow(size_t newSize)
    8991        {
    90             if (newCapacity <= m_size)
     92            if (newSize <= m_size)
    9193                return;
    9294
    93             if (newCapacity <= SegmentSize) {
    94                 m_inlineSegment.resize(newCapacity);
    95                 m_size = newCapacity;
     95            if (newSize <= SegmentSize) {
     96                m_inlineSegment.resize(newSize);
     97                m_size = newSize;
    9698                return;
    9799            }
    98100
    99             size_t numSegments = newCapacity / SegmentSize;
    100             size_t extra = newCapacity % SegmentSize;
     101            size_t newNumSegments = newSize / SegmentSize;
     102            size_t extra = newSize % SegmentSize;
    101103            if (extra)
    102                 numSegments++;
    103             size_t oldSize = m_segments.size();
     104                newNumSegments++;
     105            size_t oldNumSegments = m_segments.size();
    104106
    105             if (numSegments == oldSize) {
     107            if (newNumSegments == oldNumSegments) {
    106108                m_segments.last()->resize(extra);
    107                 m_size = newCapacity;
     109                m_size = newSize;
    108110                return;
    109111            }
     
    111113            m_segments.last()->resize(SegmentSize);
    112114
    113             m_segments.resize(numSegments);
     115            m_segments.resize(newNumSegments);
    114116
    115             ASSERT(oldSize < m_segments.size());
    116             for (size_t i = oldSize; i < (numSegments - 1); i++) {
     117            ASSERT(oldNumSegments < m_segments.size());
     118            for (size_t i = oldNumSegments; i < (newNumSegments - 1); i++) {
    117119                Segment* segment = new Segment;
    118120                segment->resize(SegmentSize);
     
    122124            Segment* segment = new Segment;
    123125            segment->resize(extra ? extra : SegmentSize);
    124             m_segments[numSegments - 1] = segment;
    125             m_size = newCapacity;
     126            m_currentSegmentIndex = newNumSegments - 1;
     127            m_segments[m_currentSegmentIndex] = segment;
     128            m_size = newSize;
    126129        }
    127130
     
    132135            m_segments.resize(1);
    133136            m_inlineSegment.resize(0);
     137            m_currentSegmentIndex = 0;
    134138            m_size = 0;
    135139        }
     
    137141    private:
    138142        typedef Vector<T, SegmentSize> Segment;
     143
    139144        size_t m_size;
     145        size_t m_currentSegmentIndex;
     146
    140147        Segment m_inlineSegment;
    141148        Vector<Segment*, 32> m_segments;
Note: See TracChangeset for help on using the changeset viewer.