Title: [208966] trunk/Source/_javascript_Core
Revision
208966
Author
[email protected]
Date
2016-11-22 11:16:55 -0800 (Tue, 22 Nov 2016)

Log 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):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (208965 => 208966)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-22 18:43:53 UTC (rev 208965)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-22 19:16:55 UTC (rev 208966)
@@ -1,3 +1,22 @@
+2016-11-22  Mark Lam  <[email protected]>
+
+        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):
+
 2016-11-21  Mark Lam  <[email protected]>
 
         Removed an extra space character at the end of line.

Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (208965 => 208966)


--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2016-11-22 18:43:53 UTC (rev 208965)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2016-11-22 19:16:55 UTC (rev 208966)
@@ -130,7 +130,7 @@
     PropertyNameArray m_arrayReplacerPropertyNames;
     CallType m_replacerCallType;
     CallData m_replacerCallData;
-    const String m_gap;
+    String m_gap;
 
     Vector<Holder, 16, UnsafeVectorOverflow> m_holderStack;
     String m_repeatedGap;
@@ -158,8 +158,12 @@
 
 static inline String gap(ExecState* exec, JSValue space)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     const unsigned maxGapLength = 10;
     space = unwrapBoxedPrimitive(exec, space);
+    RETURN_IF_EXCEPTION(scope, { });
 
     // If the space value is a number, create a gap string with that number of spaces.
     if (space.isNumber()) {
@@ -221,10 +225,14 @@
     , m_usingArrayReplacer(false)
     , m_arrayReplacerPropertyNames(exec, PropertyNameMode::Strings)
     , m_replacerCallType(CallType::None)
-    , m_gap(gap(exec, space.get()))
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
+
+    m_gap = gap(exec, space.get());
+    if (UNLIKELY(scope.exception()))
+        return;
+
     if (!m_replacer.isObject())
         return;
 
@@ -232,6 +240,8 @@
         m_usingArrayReplacer = true;
         Handle<JSObject> array = m_replacer.asObject();
         unsigned length = array->get(exec, vm.propertyNames->length).toUInt32(exec);
+        if (UNLIKELY(scope.exception()))
+            return;
         for (unsigned i = 0; i < length; ++i) {
             JSValue name = array->get(exec, i);
             if (UNLIKELY(scope.exception()))
@@ -263,10 +273,12 @@
 
     StringBuilder result;
     Holder root(Holder::RootHolder, vm, object);
-    if (appendStringifiedValue(result, value.get(), root, emptyPropertyName) != StringifySucceeded)
+    auto stringifyResult = appendStringifiedValue(result, value.get(), root, emptyPropertyName);
+    ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
+    if (UNLIKELY(stringifyResult != StringifySucceeded))
         return Local<Unknown>(vm, jsUndefined());
-    RETURN_IF_EXCEPTION(scope, Local<Unknown>(vm, jsNull()));
 
+    scope.release();
     return Local<Unknown>(vm, jsString(m_exec, result.toString()));
 }
 
@@ -280,11 +292,14 @@
     
     JSObject* object = asObject(value);
     PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
-    if (!object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot))
+    bool hasProperty = object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot);
+    ASSERT(!scope.exception() || !hasProperty);
+    if (!hasProperty)
         return value;
 
     JSValue toJSONFunction = slot.getValue(m_exec, vm.propertyNames->toJSON);
-    RETURN_IF_EXCEPTION(scope, JSValue());
+    RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
     return toJSONImpl(value, toJSONFunction, propertyName);
 }
 
@@ -387,6 +402,7 @@
     do {
         while (m_holderStack.last().appendNextProperty(*this, builder))
             RETURN_IF_EXCEPTION(scope, StringifyFailed);
+        RETURN_IF_EXCEPTION(scope, StringifyFailed);
         m_holderStack.removeLast();
     } while (!m_holderStack.isEmpty());
     return StringifySucceeded;
@@ -457,8 +473,10 @@
             if (m_isJSArray)
                 m_size = asArray(m_object.get())->length();
             else {
-                m_size = m_object->get(exec, vm.propertyNames->length).toUInt32(exec);
+                JSValue value = m_object->get(exec, vm.propertyNames->length);
                 RETURN_IF_EXCEPTION(scope, false);
+                m_size = value.toUInt32(exec);
+                RETURN_IF_EXCEPTION(scope, false);
             }
             builder.append('[');
         } else {
@@ -536,6 +554,7 @@
         // Append the stringified value.
         stringifyResult = stringifier.appendStringifiedValue(builder, value, *this, propertyName);
     }
+    RETURN_IF_EXCEPTION(scope, false);
 
     // From this point on, no access to the this pointer or to any members, because the
     // Holder object may have moved if the call to stringify pushed a new Holder onto
@@ -653,7 +672,7 @@
                         inValue = slot.getValue(m_exec, index);
                     else
                         inValue = jsUndefined();
-                    RETURN_IF_EXCEPTION(scope, JSValue());
+                    RETURN_IF_EXCEPTION(scope, { });
                 }
                     
                 if (inValue.isObject()) {
@@ -666,11 +685,12 @@
             case ArrayEndVisitMember: {
                 JSArray* array = arrayStack.peek();
                 JSValue filteredValue = callReviver(array, jsString(m_exec, String::number(indexStack.last())), outValue);
+                RETURN_IF_EXCEPTION(scope, { });
                 if (filteredValue.isUndefined())
                     array->methodTable(vm)->deletePropertyByIndex(array, m_exec, indexStack.last());
                 else
                     array->putDirectIndex(m_exec, indexStack.last(), filteredValue, 0, PutDirectIndexShouldNotThrow);
-                RETURN_IF_EXCEPTION(scope, JSValue());
+                RETURN_IF_EXCEPTION(scope, { });
                 indexStack.last()++;
                 goto arrayStartVisitMember;
             }
@@ -686,7 +706,7 @@
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
                 object->methodTable(vm)->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
-                RETURN_IF_EXCEPTION(scope, JSValue());
+                RETURN_IF_EXCEPTION(scope, { });
             }
             objectStartVisitMember:
             FALLTHROUGH;
@@ -708,7 +728,7 @@
                     inValue = jsUndefined();
 
                 // The holder may be modified by the reviver function so any lookup may throw
-                RETURN_IF_EXCEPTION(scope, JSValue());
+                RETURN_IF_EXCEPTION(scope, { });
 
                 if (inValue.isObject()) {
                     stateStack.append(ObjectEndVisitMember);
@@ -722,11 +742,12 @@
                 Identifier prop = propertyStack.last()[indexStack.last()];
                 PutPropertySlot slot(object);
                 JSValue filteredValue = callReviver(object, jsString(m_exec, prop.string()), outValue);
+                RETURN_IF_EXCEPTION(scope, { });
                 if (filteredValue.isUndefined())
                     object->methodTable(vm)->deleteProperty(object, m_exec, prop);
                 else
                     object->methodTable(vm)->put(object, m_exec, prop, filteredValue, slot);
-                RETURN_IF_EXCEPTION(scope, JSValue());
+                RETURN_IF_EXCEPTION(scope, { });
                 indexStack.last()++;
                 goto objectStartVisitMember;
             }
@@ -750,6 +771,8 @@
     JSObject* finalHolder = constructEmptyObject(m_exec);
     PutPropertySlot slot(finalHolder);
     finalHolder->methodTable(vm)->put(finalHolder, m_exec, vm.propertyNames->emptyIdentifier, outValue, slot);
+    RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
     return callReviver(finalHolder, jsEmptyString(m_exec), outValue);
 }
 
@@ -762,7 +785,7 @@
     if (!exec->argumentCount())
         return throwVMError(exec, scope, createError(exec, ASCIILiteral("JSON.parse requires at least one parameter")));
     auto viewWithString = exec->uncheckedArgument(0).toString(exec)->viewWithUnderlyingString(*exec);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    RETURN_IF_EXCEPTION(scope, { });
     StringView view = viewWithString.view;
 
     JSValue unfiltered;
@@ -770,13 +793,19 @@
     if (view.is8Bit()) {
         LiteralParser<LChar> jsonParser(exec, view.characters8(), view.length(), StrictJSON);
         unfiltered = jsonParser.tryLiteralParse();
-        if (!unfiltered)
+        ASSERT(!scope.exception() || !unfiltered);
+        if (!unfiltered) {
+            RETURN_IF_EXCEPTION(scope, { });
             return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
+        }
     } else {
         LiteralParser<UChar> jsonParser(exec, view.characters16(), view.length(), StrictJSON);
         unfiltered = jsonParser.tryLiteralParse();
-        if (!unfiltered)
+        ASSERT(!scope.exception() || !unfiltered);
+        if (!unfiltered) {
+            RETURN_IF_EXCEPTION(scope, { });
             return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
+        }
     }
     
     if (exec->argumentCount() < 2)
@@ -787,6 +816,7 @@
     CallType callType = getCallData(function, callData);
     if (callType == CallType::None)
         return JSValue::encode(unfiltered);
+    scope.release();
     return JSValue::encode(Walker(exec, Local<JSObject>(vm, asObject(function)), callType, callData).walk(unfiltered));
 }
 
@@ -802,7 +832,10 @@
     Local<Unknown> value(vm, exec->uncheckedArgument(0));
     Local<Unknown> replacer(vm, exec->argument(1));
     Local<Unknown> space(vm, exec->argument(2));
-    JSValue result = Stringifier(exec, replacer, space).stringify(value).get();
+    Stringifier stringifier(exec, replacer, space);
+    RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
+    JSValue result = stringifier.stringify(value).get();
     return JSValue::encode(result);
 }
 
@@ -824,9 +857,13 @@
 
 String JSONStringify(ExecState* exec, JSValue value, unsigned indent)
 {
-    LocalScope scope(exec->vm());
-    Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->vm(), jsNull()), Local<Unknown>(exec->vm(), jsNumber(indent))).stringify(Local<Unknown>(exec->vm(), value));
-    if (result.isUndefinedOrNull())
+    VM& vm = exec->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    LocalScope scope(vm);
+    Stringifier stringifier(exec, Local<Unknown>(vm, jsNull()), Local<Unknown>(vm, jsNumber(indent)));
+    RETURN_IF_EXCEPTION(throwScope, { });
+    Local<Unknown> result = stringifier.stringify(Local<Unknown>(vm, value));
+    if (UNLIKELY(throwScope.exception()) || result.isUndefinedOrNull())
         return String();
     return result.getString(exec);
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to