Modified: trunk/JSTests/ChangeLog (239354 => 239355)
--- trunk/JSTests/ChangeLog 2018-12-18 22:14:20 UTC (rev 239354)
+++ trunk/JSTests/ChangeLog 2018-12-18 22:24:33 UTC (rev 239355)
@@ -1,3 +1,13 @@
+2018-12-18 Mark Lam <[email protected]>
+
+ JSON.stringify() should throw OOM on StringBuilder overflows.
+ https://bugs.webkit.org/show_bug.cgi?id=192822
+ <rdar://problem/46670577>
+
+ Reviewed by Saam Barati.
+
+ * stress/json-stringify-string-builder-overflow.js: Added.
+
2018-12-18 Ross Kirsling <[email protected]>
Redeclaration of var over let/const/class should be a syntax error.
Added: trunk/JSTests/stress/json-stringify-string-builder-overflow.js (0 => 239355)
--- trunk/JSTests/stress/json-stringify-string-builder-overflow.js (rev 0)
+++ trunk/JSTests/stress/json-stringify-string-builder-overflow.js 2018-12-18 22:24:33 UTC (rev 239355)
@@ -0,0 +1,29 @@
+//@ slow
+//@ skip if $architecture != "arm64" and $architecture != "x86-64"
+
+var exception;
+try {
+ var str = JSON.stringify({
+ 'a1': {
+ 'a2': {
+ 'a3': {
+ 'a4': {
+ 'a5': {
+ 'a6': 'AAAAAAAAAA'
+ }
+ }
+ }
+ }
+ }
+ }, function (key, value) {
+ var val = {
+ 'A': true,
+ };
+ return val;
+ }, 1);
+} catch (e) {
+ exception = e;
+}
+
+if (exception != "Error: Out of memory")
+ throw "FAILED";
Modified: trunk/Source/_javascript_Core/ChangeLog (239354 => 239355)
--- trunk/Source/_javascript_Core/ChangeLog 2018-12-18 22:14:20 UTC (rev 239354)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-12-18 22:24:33 UTC (rev 239355)
@@ -1,3 +1,16 @@
+2018-12-18 Mark Lam <[email protected]>
+
+ JSON.stringify() should throw OOM on StringBuilder overflows.
+ https://bugs.webkit.org/show_bug.cgi?id=192822
+ <rdar://problem/46670577>
+
+ Reviewed by Saam Barati.
+
+ * runtime/JSONObject.cpp:
+ (JSC::Stringifier::stringify):
+ (JSC::Stringifier::appendStringifiedValue):
+ (JSC::Stringifier::Holder::appendNextProperty):
+
2018-12-18 Ross Kirsling <[email protected]>
Redeclaration of var over let/const/class should be a syntax error.
Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (239354 => 239355)
--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2018-12-18 22:14:20 UTC (rev 239354)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp 2018-12-18 22:24:33 UTC (rev 239355)
@@ -269,7 +269,7 @@
JSObject* object = nullptr;
if (isCallableReplacer()) {
object = constructEmptyObject(m_exec);
- RETURN_IF_EXCEPTION(scope, jsNull());
+ RETURN_IF_EXCEPTION(scope, jsUndefined());
object->putDirect(vm, vm.propertyNames->emptyIdentifier, value);
}
@@ -276,10 +276,13 @@
StringBuilder result(StringBuilder::OverflowHandler::RecordOverflow);
Holder root(Holder::RootHolder, object);
auto stringifyResult = appendStringifiedValue(result, value, root, emptyPropertyName);
- EXCEPTION_ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
+ RETURN_IF_EXCEPTION(scope, jsUndefined());
+ if (UNLIKELY(result.hasOverflowed())) {
+ throwOutOfMemoryError(m_exec, scope);
+ return jsUndefined();
+ }
if (UNLIKELY(stringifyResult != StringifySucceeded))
return jsUndefined();
-
RELEASE_AND_RETURN(scope, jsString(m_exec, result.toString()));
}
@@ -359,10 +362,6 @@
const String& string = asString(value)->value(m_exec);
RETURN_IF_EXCEPTION(scope, StringifyFailed);
builder.appendQuotedJSONString(string);
- if (UNLIKELY(builder.hasOverflowed())) {
- throwOutOfMemoryError(m_exec, scope);
- return StringifyFailed;
- }
return StringifySucceeded;
}
@@ -391,6 +390,9 @@
return StringifyFailedDueToUndefinedOrSymbolValue;
}
+ if (UNLIKELY(builder.hasOverflowed()))
+ return StringifyFailed;
+
// Handle cycle detection, and put the holder on the stack.
for (unsigned i = 0; i < m_holderStack.size(); i++) {
if (m_holderStack[i].object() == object) {
@@ -410,6 +412,8 @@
while (m_holderStack.last().appendNextProperty(*this, builder))
RETURN_IF_EXCEPTION(scope, StringifyFailed);
RETURN_IF_EXCEPTION(scope, StringifyFailed);
+ if (UNLIKELY(builder.hasOverflowed()))
+ return StringifyFailed;
m_holderStack.removeLast();
m_objectStack.removeLast();
} while (!m_holderStack.isEmpty());
@@ -493,6 +497,8 @@
}
stringifier.indent();
}
+ if (UNLIKELY(builder.hasOverflowed()))
+ return false;
// Last time through, finish up and return false.
if (m_index == m_size) {