JSC::createError needs to check for OOM in errorDescriptionForValue
authortzagallo@apple.com <tzagallo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 22:12:12 +0000 (22:12 +0000)
committertzagallo@apple.com <tzagallo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Mar 2019 22:12:12 +0000 (22:12 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196032
<rdar://problem/46842740>

Reviewed by Mark Lam.

JSTests:

* stress/create-error-out-of-memory-rope-string.js: Added.

Source/JavaScriptCore:

We were missing exceptions checks at two levels:
- In errorDescriptionForValue, when the value is a string, we should
  check that JSString::value returns a valid string, since we might run
  out of memory if it is a rope and we need to resolve it.
- In createError, we should check for the result of errorDescriptionForValue
  before concatenating it with the message provided by the caller.

* runtime/ExceptionHelpers.cpp:
(JSC::errorDescriptionForValue):
(JSC::createError):
* runtime/ExceptionHelpers.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243246 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/create-error-out-of-memory-rope-string.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.h

index eddd85d..d7c5ee8 100644 (file)
@@ -1,3 +1,13 @@
+2019-03-20  Tadeu Zagallo  <tzagallo@apple.com>
+
+        JSC::createError needs to check for OOM in errorDescriptionForValue
+        https://bugs.webkit.org/show_bug.cgi?id=196032
+        <rdar://problem/46842740>
+
+        Reviewed by Mark Lam.
+
+        * stress/create-error-out-of-memory-rope-string.js: Added.
+
 2019-03-19  Yusuke Suzuki  <ysuzuki@apple.com>
 
         Unreviewed, reduce # of iterations to avoid timing out after r242991
diff --git a/JSTests/stress/create-error-out-of-memory-rope-string.js b/JSTests/stress/create-error-out-of-memory-rope-string.js
new file mode 100644 (file)
index 0000000..c34191c
--- /dev/null
@@ -0,0 +1,3 @@
+var foo = 'yy?x\uFFFD$w    5?\uFFFDo\uFFFD?\uFFFD\'i?\uFFFDE-N\uFFFD\uFFFD6_\uFFFD\\ d';
+foo = foo.padEnd(2147483644, 1);
+eval('foo()');
index 2ba4a0c..4de4bd4 100644 (file)
@@ -1,3 +1,23 @@
+2019-03-20  Tadeu Zagallo  <tzagallo@apple.com>
+
+        JSC::createError needs to check for OOM in errorDescriptionForValue
+        https://bugs.webkit.org/show_bug.cgi?id=196032
+        <rdar://problem/46842740>
+
+        Reviewed by Mark Lam.
+
+        We were missing exceptions checks at two levels:
+        - In errorDescriptionForValue, when the value is a string, we should
+          check that JSString::value returns a valid string, since we might run
+          out of memory if it is a rope and we need to resolve it.
+        - In createError, we should check for the result of errorDescriptionForValue
+          before concatenating it with the message provided by the caller.
+
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::errorDescriptionForValue):
+        (JSC::createError):
+        * runtime/ExceptionHelpers.h:
+
 2019-03-20  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: DOM: include window as part of any event listener chain
index 95ae44c..f8de0e4 100644 (file)
@@ -89,21 +89,26 @@ JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
     return createReferenceError(exec, message);
 }
     
-JSString* errorDescriptionForValue(ExecState* exec, JSValue v)
+String errorDescriptionForValue(ExecState* exec, JSValue v)
 {
-    if (v.isString())
-        return jsNontrivialString(exec, makeString('"', asString(v)->value(exec), '"'));
+    if (v.isString()) {
+        String string = asString(v)->value(exec);
+        if (!string)
+            return string;
+        return tryMakeString('"', string, '"');
+    }
+
     if (v.isSymbol())
-        return jsNontrivialString(exec, asSymbol(v)->descriptiveString());
+        return asSymbol(v)->descriptiveString();
     if (v.isObject()) {
         VM& vm = exec->vm();
         CallData callData;
         JSObject* object = asObject(v);
         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
-            return vm.smallStrings.functionString();
-        return jsString(exec, JSObject::calculatedClassName(object));
+            return vm.smallStrings.functionString()->value(exec);
+        return JSObject::calculatedClassName(object);
     }
-    return v.toString(exec);
+    return v.toString(exec)->value(exec);
 }
     
 static String defaultApproximateSourceError(const String& originalMessage, const String& sourceText)
@@ -269,8 +274,11 @@ JSObject* createError(ExecState* exec, JSValue value, const String& message, Err
     VM& vm = exec->vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
-    String errorMessage = tryMakeString(errorDescriptionForValue(exec, value)->value(exec), ' ', message);
-    if (errorMessage.isNull())
+    String valueDescription = errorDescriptionForValue(exec, value);
+    if (!valueDescription)
+        return createOutOfMemoryError(exec);
+    String errorMessage = tryMakeString(valueDescription, ' ', message);
+    if (!errorMessage)
         return createOutOfMemoryError(exec);
     scope.assertNoException();
     JSObject* exception = createTypeError(exec, errorMessage, appender, runtimeTypeForValue(vm, value));
index d135858..aa51140 100644 (file)
@@ -54,7 +54,7 @@ JSObject* createInvalidInstanceofParameterErrorHasInstanceValueNotFunction(ExecS
 JSObject* createNotAConstructorError(ExecState*, JSValue);
 JSObject* createNotAFunctionError(ExecState*, JSValue);
 JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const String&);
-JSString* errorDescriptionForValue(ExecState*, JSValue);
+String errorDescriptionForValue(ExecState*, JSValue);
 
 JS_EXPORT_PRIVATE Exception* throwOutOfMemoryError(ExecState*, ThrowScope&);
 JS_EXPORT_PRIVATE Exception* throwStackOverflowError(ExecState*, ThrowScope&);