Ignore:
Timestamp:
Feb 19, 2010, 3:36:09 PM (15 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):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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        }
Note: See TracChangeset for help on using the changeset viewer.