Changeset 55035 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Feb 19, 2010, 3:36:09 PM (16 years ago)
Author:
[email protected]
Message:

JSString::getIndex() calls value() to resolve the string value (is a rope)
to a UString, then passes the result to jsSingleCharacterSubstring without
checking for an exception. In case of out-of-memory the returned UString
is null(), which may result in an out-of-buounds substring being created.
This is bad.

Reviewed by Oliver Hunt.

Simple fix is to be able to get an index from a rope without resolving to
UString. This may be a useful optimization in some test cases.

The same bug exists in some other methods is JSString, these can be fixed
by changing them to call getIndex().

  • runtime/JSString.cpp:

(JSC::JSString::resolveRope):
(JSC::JSString::getStringPropertyDescriptor):

  • runtime/JSString.h:

(JSC::jsSingleCharacterSubstring):
(JSC::JSString::getIndex):
(JSC::jsSingleCharacterString):
(JSC::JSString::getStringPropertySlot):

  • runtime/UStringImpl.cpp:

(JSC::singleCharacterSubstring):

  • runtime/UStringImpl.h:

(JSC::UStringImpl::singleCharacterSubstring):

Location:
trunk/JavaScriptCore/runtime
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/JSString.cpp

    r54843 r55035  
    5151        m_value = newImpl;
    5252    else {
    53         for (unsigned i = 0; i < m_fiberCount; ++i) {
    54             m_other.m_fibers[i]->deref();
    55             m_other.m_fibers[i] = 0;
    56         }
    57         m_fiberCount = 0;
    58         ASSERT(!isRope());
    59         ASSERT(m_value == UString());
    6053        throwOutOfMemoryError(exec);
    6154        return;
     
    188181    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
    189182    if (isStrictUInt32 && i < m_length) {
    190         descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly);
     183        descriptor.setDescriptor(getIndex(exec, i), DontDelete | ReadOnly);
    191184        return true;
    192185    }
  • trunk/JavaScriptCore/runtime/JSString.h

    r54925 r55035  
    4242    JSString* jsSingleCharacterString(JSGlobalData*, UChar);
    4343    JSString* jsSingleCharacterString(ExecState*, UChar);
    44     JSString* jsSingleCharacterSubstring(JSGlobalData*, const UString&, unsigned offset);
    4544    JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset);
    4645    JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length);
     
    366365    }
    367366
    368     inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset)
    369     {
     367    inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset)
     368    {
     369        JSGlobalData* globalData = &exec->globalData();
     370
    370371        ASSERT(offset < static_cast<unsigned>(s.size()));
    371372        UChar c = s.data()[offset];
     
    392393    {
    393394        ASSERT(canGetIndex(i));
    394         return jsSingleCharacterSubstring(&exec->globalData(), value(exec), i);
     395        if (!isRope())
     396            return jsSingleCharacterSubstring(exec, m_value, i);
     397
     398        if (i < m_other.m_fibers[0]->length())
     399            return jsString(exec, singleCharacterSubstring(m_other.m_fibers[0], i));
     400        i -= m_other.m_fibers[0]->length();
     401
     402        ASSERT(m_fiberCount >= 2);
     403        if (i < m_other.m_fibers[1]->length())
     404            return jsString(exec, singleCharacterSubstring(m_other.m_fibers[1], i));
     405        i -= m_other.m_fibers[1]->length();
     406
     407        ASSERT(m_fiberCount == 3);
     408        ASSERT(i < m_other.m_fibers[2]->length());
     409        return jsString(exec, singleCharacterSubstring(m_other.m_fibers[2], i));
    395410    }
    396411
     
    446461    inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
    447462    inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
    448     inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { return jsSingleCharacterSubstring(&exec->globalData(), s, offset); }
    449463    inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
    450464    inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
     
    462476        unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
    463477        if (isStrictUInt32 && i < m_length) {
    464             slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i));
     478            slot.setValue(getIndex(exec, i));
    465479            return true;
    466480        }
     
    472486    {
    473487        if (propertyName < m_length) {
    474             slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName));
     488            slot.setValue(getIndex(exec, propertyName));
    475489            return true;
    476490        }
  • trunk/JavaScriptCore/runtime/UStringImpl.cpp

    r54843 r55035  
    150150}
    151151
     152PassRefPtr<UStringImpl> singleCharacterSubstring(UStringOrRopeImpl* impl, unsigned index)
     153{
     154top:
     155    if (impl->isRope()) {
     156        URopeImpl* rope = static_cast<URopeImpl*>(impl);
     157        for (unsigned i = 0; i < rope->m_fiberCount; ++i) {
     158            UStringOrRopeImpl* currentFiber = rope->fibers(i);
     159            unsigned fiberLength = currentFiber->length();
     160            if (index < fiberLength) {
     161                impl = currentFiber;
     162                goto top;
     163            }
     164            index -= fiberLength;
     165        }
     166        CRASH();
     167    }
     168
     169    return static_cast<UStringImpl*>(impl)->singleCharacterSubstring(index);
     170}
     171
    152172} // namespace JSC
  • trunk/JavaScriptCore/runtime/UStringImpl.h

    r54870 r55035  
    213213    }
    214214
     215    PassRefPtr<UStringImpl> singleCharacterSubstring(unsigned index) { ASSERT(index < length()); return create(this, index, 1); }
     216
    215217private:
    216218    // For SmallStringStorage, which allocates an array and uses an in-place new.
     
    343345
    344346    friend class UStringOrRopeImpl;
     347    friend PassRefPtr<UStringImpl> singleCharacterSubstring(UStringOrRopeImpl* ropeoid, unsigned index);
    345348};
    346349
     
    355358bool equal(const UStringImpl*, const UStringImpl*);
    356359
     360PassRefPtr<UStringImpl> singleCharacterSubstring(UStringOrRopeImpl* ropeoid, unsigned index);
     361
    357362}
    358363
Note: See TracChangeset for help on using the changeset viewer.