Changeset 55035 in webkit


Ignore:
Timestamp:
Feb 19, 2010 3:36:09 PM (14 years ago)
Author:
barraclough@apple.com
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
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r55027 r55035  
     12010-02-19  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        JSString::getIndex() calls value() to resolve the string value (is a rope)
     6        to a UString, then passes the result to jsSingleCharacterSubstring without
     7        checking for an exception.  In case of out-of-memory the returned UString
     8        is null(), which may result in an out-of-buounds substring being created.
     9        This is bad.
     10
     11        Simple fix is to be able to get an index from a rope without resolving to
     12        UString.  This may be a useful optimization in some test cases.
     13
     14        The same bug exists in some other methods is JSString, these can be fixed
     15        by changing them to call getIndex().
     16
     17        * runtime/JSString.cpp:
     18        (JSC::JSString::resolveRope):
     19        (JSC::JSString::getStringPropertyDescriptor):
     20        * runtime/JSString.h:
     21        (JSC::jsSingleCharacterSubstring):
     22        (JSC::JSString::getIndex):
     23        (JSC::jsSingleCharacterString):
     24        (JSC::JSString::getStringPropertySlot):
     25        * runtime/UStringImpl.cpp:
     26        (JSC::singleCharacterSubstring):
     27        * runtime/UStringImpl.h:
     28        (JSC::UStringImpl::singleCharacterSubstring):
     29
    1302010-02-19  Oliver Hunt  <oliver@apple.com>
    231
  • 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.