Changeset 196721 in webkit


Ignore:
Timestamp:
Feb 17, 2016 2:03:56 PM (8 years ago)
Author:
mark.lam@apple.com
Message:

StringPrototype functions should check for exceptions after calling JSString::value().
https://bugs.webkit.org/show_bug.cgi?id=154340

Reviewed by Filip Pizlo.

JSString::value() can throw an exception if the JS string is a rope and value()
needs to resolve the rope but encounters an OutOfMemory error. If value() is not
able to resolve the rope, it will return a null string (in addition to throwing
the exception). If StringPrototype functions do not check for exceptions after
calling JSString::value(), they may eventually use the returned null string and
crash the VM.

The fix is to add all the necessary exception checks, and do the appropriate
handling if needed.

Also in a few place where when an exception is detected, we return JSValue(), I
changed it to return jsUndefined() instead to be consistent with the rest of the
file.

  • runtime/StringPrototype.cpp:

(JSC::replaceUsingRegExpSearch):
(JSC::stringProtoFuncMatch):
(JSC::stringProtoFuncSlice):
(JSC::stringProtoFuncSplit):
(JSC::stringProtoFuncLocaleCompare):
(JSC::stringProtoFuncBig):
(JSC::stringProtoFuncSmall):
(JSC::stringProtoFuncBlink):
(JSC::stringProtoFuncBold):
(JSC::stringProtoFuncFixed):
(JSC::stringProtoFuncItalics):
(JSC::stringProtoFuncStrike):
(JSC::stringProtoFuncSub):
(JSC::stringProtoFuncSup):
(JSC::stringProtoFuncFontcolor):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncAnchor):
(JSC::stringProtoFuncLink):
(JSC::trimString):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r196704 r196721  
     12016-02-17  Mark Lam  <mark.lam@apple.com>
     2
     3        StringPrototype functions should check for exceptions after calling JSString::value().
     4        https://bugs.webkit.org/show_bug.cgi?id=154340
     5
     6        Reviewed by Filip Pizlo.
     7
     8        JSString::value() can throw an exception if the JS string is a rope and value()
     9        needs to resolve the rope but encounters an OutOfMemory error.  If value() is not
     10        able to resolve the rope, it will return a null string (in addition to throwing
     11        the exception).  If StringPrototype functions do not check for exceptions after
     12        calling JSString::value(), they may eventually use the returned null string and
     13        crash the VM.
     14
     15        The fix is to add all the necessary exception checks, and do the appropriate
     16        handling if needed.
     17
     18        Also in a few place where when an exception is detected, we return JSValue(), I
     19        changed it to return jsUndefined() instead to be consistent with the rest of the
     20        file.
     21
     22        * runtime/StringPrototype.cpp:
     23        (JSC::replaceUsingRegExpSearch):
     24        (JSC::stringProtoFuncMatch):
     25        (JSC::stringProtoFuncSlice):
     26        (JSC::stringProtoFuncSplit):
     27        (JSC::stringProtoFuncLocaleCompare):
     28        (JSC::stringProtoFuncBig):
     29        (JSC::stringProtoFuncSmall):
     30        (JSC::stringProtoFuncBlink):
     31        (JSC::stringProtoFuncBold):
     32        (JSC::stringProtoFuncFixed):
     33        (JSC::stringProtoFuncItalics):
     34        (JSC::stringProtoFuncStrike):
     35        (JSC::stringProtoFuncSub):
     36        (JSC::stringProtoFuncSup):
     37        (JSC::stringProtoFuncFontcolor):
     38        (JSC::stringProtoFuncFontsize):
     39        (JSC::stringProtoFuncAnchor):
     40        (JSC::stringProtoFuncLink):
     41        (JSC::trimString):
     42
    1432016-02-17  Commit Queue  <commit-queue@webkit.org>
    244
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r196547 r196721  
    491491    CallData callData;
    492492    CallType callType = getCallData(replaceValue, callData);
    493     if (callType == CallTypeNone)
     493    if (callType == CallTypeNone) {
    494494        replacementString = replaceValue.toString(exec)->value(exec);
     495        if (exec->hadException())
     496            return JSValue::encode(jsUndefined());
     497    }
    495498
    496499    const String& source = string->value(exec);
    497500    unsigned sourceLen = source.length();
    498501    if (exec->hadException())
    499         return JSValue::encode(JSValue());
     502        return JSValue::encode(jsUndefined());
    500503    RegExpObject* regExpObject = asRegExpObject(searchValue);
    501504    RegExp* regExp = regExpObject->regExp();
     
    506509        regExpObject->setLastIndex(exec, 0);
    507510        if (exec->hadException())
    508             return JSValue::encode(JSValue());
     511            return JSValue::encode(jsUndefined());
    509512
    510513        if (callType == CallTypeNone && !replacementString.length())
     
    527530        CachedCall cachedCall(exec, func, argCount);
    528531        if (exec->hadException())
    529             return JSValue::encode(jsNull());
     532            return JSValue::encode(jsUndefined());
    530533        VM* vm = &exec->vm();
    531534        if (source.is8Bit()) {
     
    556559                replacements.append(jsResult.toString(exec)->value(exec));
    557560                if (exec->hadException())
    558                     break;
     561                    return JSValue::encode(jsUndefined());
    559562
    560563                lastIndex = result.end;
     
    595598                replacements.append(jsResult.toString(exec)->value(exec));
    596599                if (exec->hadException())
    597                     break;
     600                    return JSValue::encode(jsUndefined());
    598601
    599602                lastIndex = result.end;
     
    636639                replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec));
    637640                if (exec->hadException())
    638                     break;
     641                    return JSValue::encode(jsUndefined());
    639642            } else {
    640643                int replLen = replacementString.length();
     
    991994            regExpObject->setLastIndex(exec, 0);
    992995            if (exec->hadException())
    993                 return JSValue::encode(JSValue());
     996                return JSValue::encode(jsUndefined());
    994997        }
    995998    } else {
     
    10001003         *  Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string.
    10011004         */
    1002         regExp = RegExp::create(exec->vm(), a0.isUndefined() ? emptyString() : a0.toString(exec)->value(exec), NoFlags);
     1005        String patternString = emptyString();
     1006        if (!a0.isUndefined()) {
     1007            patternString = a0.toString(exec)->value(exec);
     1008            if (exec->hadException())
     1009                return JSValue::encode(jsUndefined());
     1010        }
     1011        regExp = RegExp::create(exec->vm(), patternString, NoFlags);
    10031012        if (!regExp->isValid())
    10041013            return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
     
    10431052        return throwVMTypeError(exec);
    10441053    String s = thisValue.toString(exec)->value(exec);
     1054    if (exec->hadException())
     1055        return JSValue::encode(jsUndefined());
     1056
    10451057    int len = s.length();
    10461058    RELEASE_ASSERT(len >= 0);
     
    11051117    // 6. Let s be the number of characters in S.
    11061118    String input = thisValue.toString(exec)->value(exec);
     1119    if (exec->hadException())
     1120        return JSValue::encode(jsUndefined());
     1121    ASSERT(!input.isNull());
    11071122
    11081123    // 3. Let A be a new array created as if by the expression new Array()
     
    12311246    } else {
    12321247        String separator = separatorValue.toString(exec)->value(exec);
     1248        if (exec->hadException())
     1249            return JSValue::encode(jsUndefined());
    12331250
    12341251        // 9. If lim == 0, return A.
     
    14401457        return throwVMTypeError(exec);
    14411458    String s = thisValue.toString(exec)->value(exec);
     1459    if (exec->hadException())
     1460        return JSValue::encode(jsUndefined());
    14421461
    14431462    JSValue a0 = exec->argument(0);
    1444     return JSValue::encode(jsNumber(Collator().collate(s, a0.toString(exec)->value(exec))));
     1463    String str = a0.toString(exec)->value(exec);
     1464    if (exec->hadException())
     1465        return JSValue::encode(jsUndefined());
     1466    return JSValue::encode(jsNumber(Collator().collate(s, str)));
    14451467}
    14461468
     
    15501572        return throwVMTypeError(exec);
    15511573    String s = thisValue.toString(exec)->value(exec);
     1574    if (exec->hadException())
     1575        return JSValue::encode(jsUndefined());
    15521576    return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
    15531577}
     
    15591583        return throwVMTypeError(exec);
    15601584    String s = thisValue.toString(exec)->value(exec);
     1585    if (exec->hadException())
     1586        return JSValue::encode(jsUndefined());
    15611587    return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
    15621588}
     
    15681594        return throwVMTypeError(exec);
    15691595    String s = thisValue.toString(exec)->value(exec);
     1596    if (exec->hadException())
     1597        return JSValue::encode(jsUndefined());
    15701598    return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
    15711599}
     
    15771605        return throwVMTypeError(exec);
    15781606    String s = thisValue.toString(exec)->value(exec);
     1607    if (exec->hadException())
     1608        return JSValue::encode(jsUndefined());
    15791609    return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
    15801610}
     
    15861616        return throwVMTypeError(exec);
    15871617    String s = thisValue.toString(exec)->value(exec);
     1618    if (exec->hadException())
     1619        return JSValue::encode(jsUndefined());
    15881620    return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
    15891621}
     
    15951627        return throwVMTypeError(exec);
    15961628    String s = thisValue.toString(exec)->value(exec);
     1629    if (exec->hadException())
     1630        return JSValue::encode(jsUndefined());
    15971631    return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
    15981632}
     
    16041638        return throwVMTypeError(exec);
    16051639    String s = thisValue.toString(exec)->value(exec);
     1640    if (exec->hadException())
     1641        return JSValue::encode(jsUndefined());
    16061642    return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
    16071643}
     
    16131649        return throwVMTypeError(exec);
    16141650    String s = thisValue.toString(exec)->value(exec);
     1651    if (exec->hadException())
     1652        return JSValue::encode(jsUndefined());
    16151653    return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
    16161654}
     
    16221660        return throwVMTypeError(exec);
    16231661    String s = thisValue.toString(exec)->value(exec);
     1662    if (exec->hadException())
     1663        return JSValue::encode(jsUndefined());
    16241664    return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
    16251665}
     
    16311671        return throwVMTypeError(exec);
    16321672    String s = thisValue.toString(exec)->value(exec);
     1673    if (exec->hadException())
     1674        return JSValue::encode(jsUndefined());
     1675
    16331676    JSValue a0 = exec->argument(0);
    16341677    String color = a0.toWTFString(exec);
     
    16441687        return throwVMTypeError(exec);
    16451688    String s = thisValue.toString(exec)->value(exec);
     1689    if (exec->hadException())
     1690        return JSValue::encode(jsUndefined());
     1691
    16461692    JSValue a0 = exec->argument(0);
    16471693
     
    16931739        return throwVMTypeError(exec);
    16941740    String s = thisValue.toString(exec)->value(exec);
     1741    if (exec->hadException())
     1742        return JSValue::encode(jsUndefined());
     1743
    16951744    JSValue a0 = exec->argument(0);
    16961745    String anchor = a0.toWTFString(exec);
     
    17061755        return throwVMTypeError(exec);
    17071756    String s = thisValue.toString(exec)->value(exec);
     1757    if (exec->hadException())
     1758        return JSValue::encode(jsUndefined());
     1759
    17081760    JSValue a0 = exec->argument(0);
    17091761    String linkText = a0.toWTFString(exec);
     
    17481800        return throwTypeError(exec);
    17491801    String str = thisValue.toString(exec)->value(exec);
     1802    if (exec->hadException())
     1803        return jsUndefined();
     1804
    17501805    unsigned left = 0;
    17511806    if (trimKind & TrimLeft) {
Note: See TracChangeset for help on using the changeset viewer.