Changeset 208966 in webkit


Ignore:
Timestamp:
Nov 22, 2016 11:16:55 AM (7 years ago)
Author:
mark.lam@apple.com
Message:

Fix exception scope verification failures in JSONObject.cpp.
https://bugs.webkit.org/show_bug.cgi?id=165025

Reviewed by Saam Barati.

  • runtime/JSONObject.cpp:

(JSC::gap):
(JSC::Stringifier::Stringifier):
(JSC::Stringifier::stringify):
(JSC::Stringifier::toJSON):
(JSC::Stringifier::appendStringifiedValue):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):
(JSC::JSONStringify):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r208957 r208966  
     12016-11-22  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix exception scope verification failures in JSONObject.cpp.
     4        https://bugs.webkit.org/show_bug.cgi?id=165025
     5
     6        Reviewed by Saam Barati.
     7
     8        * runtime/JSONObject.cpp:
     9        (JSC::gap):
     10        (JSC::Stringifier::Stringifier):
     11        (JSC::Stringifier::stringify):
     12        (JSC::Stringifier::toJSON):
     13        (JSC::Stringifier::appendStringifiedValue):
     14        (JSC::Stringifier::Holder::appendNextProperty):
     15        (JSC::Walker::walk):
     16        (JSC::JSONProtoFuncParse):
     17        (JSC::JSONProtoFuncStringify):
     18        (JSC::JSONStringify):
     19
    1202016-11-21  Mark Lam  <mark.lam@apple.com>
    221
  • trunk/Source/JavaScriptCore/runtime/JSONObject.cpp

    r208767 r208966  
    131131    CallType m_replacerCallType;
    132132    CallData m_replacerCallData;
    133     const String m_gap;
     133    String m_gap;
    134134
    135135    Vector<Holder, 16, UnsafeVectorOverflow> m_holderStack;
     
    159159static inline String gap(ExecState* exec, JSValue space)
    160160{
     161    VM& vm = exec->vm();
     162    auto scope = DECLARE_THROW_SCOPE(vm);
     163
    161164    const unsigned maxGapLength = 10;
    162165    space = unwrapBoxedPrimitive(exec, space);
     166    RETURN_IF_EXCEPTION(scope, { });
    163167
    164168    // If the space value is a number, create a gap string with that number of spaces.
     
    222226    , m_arrayReplacerPropertyNames(exec, PropertyNameMode::Strings)
    223227    , m_replacerCallType(CallType::None)
    224     , m_gap(gap(exec, space.get()))
    225228{
    226229    VM& vm = exec->vm();
    227230    auto scope = DECLARE_THROW_SCOPE(vm);
     231
     232    m_gap = gap(exec, space.get());
     233    if (UNLIKELY(scope.exception()))
     234        return;
     235
    228236    if (!m_replacer.isObject())
    229237        return;
     
    233241        Handle<JSObject> array = m_replacer.asObject();
    234242        unsigned length = array->get(exec, vm.propertyNames->length).toUInt32(exec);
     243        if (UNLIKELY(scope.exception()))
     244            return;
    235245        for (unsigned i = 0; i < length; ++i) {
    236246            JSValue name = array->get(exec, i);
     
    264274    StringBuilder result;
    265275    Holder root(Holder::RootHolder, vm, object);
    266     if (appendStringifiedValue(result, value.get(), root, emptyPropertyName) != StringifySucceeded)
     276    auto stringifyResult = appendStringifiedValue(result, value.get(), root, emptyPropertyName);
     277    ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
     278    if (UNLIKELY(stringifyResult != StringifySucceeded))
    267279        return Local<Unknown>(vm, jsUndefined());
    268     RETURN_IF_EXCEPTION(scope, Local<Unknown>(vm, jsNull()));
    269 
     280
     281    scope.release();
    270282    return Local<Unknown>(vm, jsString(m_exec, result.toString()));
    271283}
     
    281293    JSObject* object = asObject(value);
    282294    PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
    283     if (!object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot))
     295    bool hasProperty = object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot);
     296    ASSERT(!scope.exception() || !hasProperty);
     297    if (!hasProperty)
    284298        return value;
    285299
    286300    JSValue toJSONFunction = slot.getValue(m_exec, vm.propertyNames->toJSON);
    287     RETURN_IF_EXCEPTION(scope, JSValue());
     301    RETURN_IF_EXCEPTION(scope, { });
     302    scope.release();
    288303    return toJSONImpl(value, toJSONFunction, propertyName);
    289304}
     
    388403        while (m_holderStack.last().appendNextProperty(*this, builder))
    389404            RETURN_IF_EXCEPTION(scope, StringifyFailed);
     405        RETURN_IF_EXCEPTION(scope, StringifyFailed);
    390406        m_holderStack.removeLast();
    391407    } while (!m_holderStack.isEmpty());
     
    458474                m_size = asArray(m_object.get())->length();
    459475            else {
    460                 m_size = m_object->get(exec, vm.propertyNames->length).toUInt32(exec);
     476                JSValue value = m_object->get(exec, vm.propertyNames->length);
     477                RETURN_IF_EXCEPTION(scope, false);
     478                m_size = value.toUInt32(exec);
    461479                RETURN_IF_EXCEPTION(scope, false);
    462480            }
     
    537555        stringifyResult = stringifier.appendStringifiedValue(builder, value, *this, propertyName);
    538556    }
     557    RETURN_IF_EXCEPTION(scope, false);
    539558
    540559    // From this point on, no access to the this pointer or to any members, because the
     
    654673                    else
    655674                        inValue = jsUndefined();
    656                     RETURN_IF_EXCEPTION(scope, JSValue());
     675                    RETURN_IF_EXCEPTION(scope, { });
    657676                }
    658677                   
     
    667686                JSArray* array = arrayStack.peek();
    668687                JSValue filteredValue = callReviver(array, jsString(m_exec, String::number(indexStack.last())), outValue);
     688                RETURN_IF_EXCEPTION(scope, { });
    669689                if (filteredValue.isUndefined())
    670690                    array->methodTable(vm)->deletePropertyByIndex(array, m_exec, indexStack.last());
    671691                else
    672692                    array->putDirectIndex(m_exec, indexStack.last(), filteredValue, 0, PutDirectIndexShouldNotThrow);
    673                 RETURN_IF_EXCEPTION(scope, JSValue());
     693                RETURN_IF_EXCEPTION(scope, { });
    674694                indexStack.last()++;
    675695                goto arrayStartVisitMember;
     
    687707                propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
    688708                object->methodTable(vm)->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
    689                 RETURN_IF_EXCEPTION(scope, JSValue());
     709                RETURN_IF_EXCEPTION(scope, { });
    690710            }
    691711            objectStartVisitMember:
     
    709729
    710730                // The holder may be modified by the reviver function so any lookup may throw
    711                 RETURN_IF_EXCEPTION(scope, JSValue());
     731                RETURN_IF_EXCEPTION(scope, { });
    712732
    713733                if (inValue.isObject()) {
     
    723743                PutPropertySlot slot(object);
    724744                JSValue filteredValue = callReviver(object, jsString(m_exec, prop.string()), outValue);
     745                RETURN_IF_EXCEPTION(scope, { });
    725746                if (filteredValue.isUndefined())
    726747                    object->methodTable(vm)->deleteProperty(object, m_exec, prop);
    727748                else
    728749                    object->methodTable(vm)->put(object, m_exec, prop, filteredValue, slot);
    729                 RETURN_IF_EXCEPTION(scope, JSValue());
     750                RETURN_IF_EXCEPTION(scope, { });
    730751                indexStack.last()++;
    731752                goto objectStartVisitMember;
     
    751772    PutPropertySlot slot(finalHolder);
    752773    finalHolder->methodTable(vm)->put(finalHolder, m_exec, vm.propertyNames->emptyIdentifier, outValue, slot);
     774    RETURN_IF_EXCEPTION(scope, { });
     775    scope.release();
    753776    return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
    754777}
     
    763786        return throwVMError(exec, scope, createError(exec, ASCIILiteral("JSON.parse requires at least one parameter")));
    764787    auto viewWithString = exec->uncheckedArgument(0).toString(exec)->viewWithUnderlyingString(*exec);
    765     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     788    RETURN_IF_EXCEPTION(scope, { });
    766789    StringView view = viewWithString.view;
    767790
     
    771794        LiteralParser<LChar> jsonParser(exec, view.characters8(), view.length(), StrictJSON);
    772795        unfiltered = jsonParser.tryLiteralParse();
    773         if (!unfiltered)
     796        ASSERT(!scope.exception() || !unfiltered);
     797        if (!unfiltered) {
     798            RETURN_IF_EXCEPTION(scope, { });
    774799            return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
     800        }
    775801    } else {
    776802        LiteralParser<UChar> jsonParser(exec, view.characters16(), view.length(), StrictJSON);
    777803        unfiltered = jsonParser.tryLiteralParse();
    778         if (!unfiltered)
     804        ASSERT(!scope.exception() || !unfiltered);
     805        if (!unfiltered) {
     806            RETURN_IF_EXCEPTION(scope, { });
    779807            return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
     808        }
    780809    }
    781810   
     
    788817    if (callType == CallType::None)
    789818        return JSValue::encode(unfiltered);
     819    scope.release();
    790820    return JSValue::encode(Walker(exec, Local<JSObject>(vm, asObject(function)), callType, callData).walk(unfiltered));
    791821}
     
    803833    Local<Unknown> replacer(vm, exec->argument(1));
    804834    Local<Unknown> space(vm, exec->argument(2));
    805     JSValue result = Stringifier(exec, replacer, space).stringify(value).get();
     835    Stringifier stringifier(exec, replacer, space);
     836    RETURN_IF_EXCEPTION(scope, { });
     837    scope.release();
     838    JSValue result = stringifier.stringify(value).get();
    806839    return JSValue::encode(result);
    807840}
     
    825858String JSONStringify(ExecState* exec, JSValue value, unsigned indent)
    826859{
    827     LocalScope scope(exec->vm());
    828     Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->vm(), jsNull()), Local<Unknown>(exec->vm(), jsNumber(indent))).stringify(Local<Unknown>(exec->vm(), value));
    829     if (result.isUndefinedOrNull())
     860    VM& vm = exec->vm();
     861    auto throwScope = DECLARE_THROW_SCOPE(vm);
     862    LocalScope scope(vm);
     863    Stringifier stringifier(exec, Local<Unknown>(vm, jsNull()), Local<Unknown>(vm, jsNumber(indent)));
     864    RETURN_IF_EXCEPTION(throwScope, { });
     865    Local<Unknown> result = stringifier.stringify(Local<Unknown>(vm, value));
     866    if (UNLIKELY(throwScope.exception()) || result.isUndefinedOrNull())
    830867        return String();
    831868    return result.getString(exec);
Note: See TracChangeset for help on using the changeset viewer.