Bug 1513665 - Add missing realm checks to some Array and Promise functions. r=anba
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 24 Jan 2019 19:22:42 +0000
changeset 512518 9bab87de8e3c8be666f0bc459519b4f26d8483a3
parent 512517 8c3a041f077f9d01e12aff3fe2dbc9beb0ed82f8
child 512519 f745bbf9f347e1946210d1559ea93693dca68b30
push id10566
push userarchaeopteryx@coole-files.de
push dateMon, 28 Jan 2019 12:41:12 +0000
treeherdermozilla-beta@69a3d7c8d04b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1513665
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1513665 - Add missing realm checks to some Array and Promise functions. r=anba Differential Revision: https://phabricator.services.mozilla.com/D17511
js/src/builtin/Array.cpp
js/src/builtin/Promise.cpp
js/src/jit-test/tests/realms/bug1513665.js
--- a/js/src/builtin/Array.cpp
+++ b/js/src/builtin/Array.cpp
@@ -3672,19 +3672,23 @@ static bool ArrayFromCallArgs(JSContext*
 
   args.rval().setObject(*obj);
   return true;
 }
 
 static bool array_of(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
-  if (IsArrayConstructor(args.thisv()) || !IsConstructor(args.thisv())) {
-    // IsArrayConstructor(this) will usually be true in practice. This is
-    // the most common path.
+  bool isArrayConstructor =
+      IsArrayConstructor(args.thisv()) &&
+      args.thisv().toObject().nonCCWRealm() == cx->realm();
+
+  if (isArrayConstructor || !IsConstructor(args.thisv())) {
+    // isArrayConstructor will usually be true in practice. This is the most
+    // common path.
     return ArrayFromCallArgs(cx, args);
   }
 
   // Step 4.
   RootedObject obj(cx);
   {
     FixedConstructArgs<1> cargs(cx);
 
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -1231,17 +1231,18 @@ static MOZ_MUST_USE bool NewPromiseCapab
   // This can't be used in Promise.all and Promise.race because we have to
   // pass the reject (and resolve, in the race case) function to thenables
   // in the list passed to all/race, which (potentially) means exposing them
   // to content.
   //
   // For Promise.all and Promise.race we can only optimize away the creation
   // of the GetCapabilitiesExecutor function, and directly allocate the
   // result promise instead of invoking the Promise constructor.
-  if (IsNativeFunction(cVal, PromiseConstructor)) {
+  if (IsNativeFunction(cVal, PromiseConstructor) &&
+      cVal.toObject().nonCCWRealm() == cx->realm()) {
     PromiseObject* promise;
     if (canOmitResolutionFunctions) {
       promise = CreatePromiseObjectWithoutResolutionFunctions(cx);
     } else {
       promise = CreatePromiseWithDefaultResolutionFunctions(
           cx, capability.resolve(), capability.reject());
     }
     if (!promise) {
@@ -4060,17 +4061,18 @@ static bool Promise_catch_impl(JSContext
   }
 
   // Step 1.
   RootedValue thenVal(cx);
   if (!GetProperty(cx, thisVal, cx->names().then, &thenVal)) {
     return false;
   }
 
-  if (IsNativeFunction(thenVal, &Promise_then)) {
+  if (IsNativeFunction(thenVal, &Promise_then) &&
+      thenVal.toObject().nonCCWRealm() == cx->realm()) {
     return Promise_then_impl(cx, thisVal, onFulfilled, onRejected, args.rval(),
                              rvalUsed);
   }
 
   return Call(cx, thenVal, thisVal, UndefinedHandleValue, onRejected,
               args.rval());
 }
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/realms/bug1513665.js
@@ -0,0 +1,24 @@
+load(libdir + "asserts.js");
+
+var g = newGlobal();
+
+function testArrayOf() {
+    var a = Array.of.call(g.Array);
+    assertEq(a instanceof g.Array, true);
+}
+testArrayOf();
+
+function testPromiseThen() {
+    var p = Promise.resolve(0);
+    p.constructor = g.Promise;
+    var r = p.then(() => {});
+    assertEq(r instanceof g.Promise, true);
+}
+testPromiseThen();
+
+function testPromiseCatch() {
+    Boolean.prototype.then = g.Promise.prototype.then;
+    assertThrowsInstanceOf(() => Promise.prototype.catch.call(false),
+                           g.TypeError);
+}
+testPromiseCatch();