Bug 1522314 - Apply realm checks for newGlobal() also to evalcx(). r=jorendorff a=lizzard
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 28 Jan 2019 21:06:03 +0000
changeset 515705 46cd2c559813e86a7828cb791a41075c8738e29e
parent 515704 e2f693bac4d4b4e2cd2360666e6e77b0b6e3ea4c
child 515706 b511d2df882c7fdbd3929608860affb914944245
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, lizzard
bugs1522314
milestone66.0
Bug 1522314 - Apply realm checks for newGlobal() also to evalcx(). r=jorendorff a=lizzard Differential Revision: https://phabricator.services.mozilla.com/D17509
js/src/jit-test/tests/realms/basic.js
js/src/shell/js.cpp
--- a/js/src/jit-test/tests/realms/basic.js
+++ b/js/src/jit-test/tests/realms/basic.js
@@ -78,10 +78,21 @@ function testTypedArrayLazyBuffer(global
 }
 testTypedArrayLazyBuffer(newGlobal());
 testTypedArrayLazyBuffer(newGlobal({sameCompartmentAs: this}));
 
 function testEvalcx() {
     var g = newGlobal();
     evalcx("this.x = 7", g);
     assertEq(g.x, 7);
+
+    g = newGlobal({newCompartment: true, invisibleToDebugger: true});
+    var ex, sb;
+    try {
+        sb = g.eval("evalcx('')");
+    } catch(e) {
+        ex = e;
+    }
+    // Check for either an exception or CCW (with --more-compartments).
+    assertEq((sb && objectGlobal(sb) === null) ||
+             ex.toString().includes("visibility"), true);
 }
 testEvalcx();
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3771,28 +3771,66 @@ static void SetStandardRealmOptions(JS::
   options.creationOptions()
       .setSharedMemoryAndAtomicsEnabled(enableSharedMemory)
 #ifdef ENABLE_BIGINT
       .setBigIntEnabled(enableBigInt)
 #endif
       .setStreamsEnabled(enableStreams);
 }
 
+static MOZ_MUST_USE bool CheckRealmOptions(JSContext* cx,
+                                           JS::RealmOptions& options,
+                                           JSPrincipals* principals) {
+  JS::RealmCreationOptions& creationOptions = options.creationOptions();
+  if (creationOptions.compartmentSpecifier() !=
+      JS::CompartmentSpecifier::ExistingCompartment) {
+    return true;
+  }
+
+  JS::Compartment* comp = creationOptions.compartment();
+
+  // All realms in a compartment must be either system or non-system.
+  bool isSystem =
+      principals && principals == cx->runtime()->trustedPrincipals();
+  if (isSystem != IsSystemCompartment(comp)) {
+    JS_ReportErrorASCII(cx,
+                        "Cannot create system and non-system realms in the "
+                        "same compartment");
+    return false;
+  }
+
+  // Debugger visibility is per-compartment, not per-realm, so make sure the
+  // requested visibility matches the existing compartment's.
+  if (creationOptions.invisibleToDebugger() != comp->invisibleToDebugger()) {
+    JS_ReportErrorASCII(cx,
+                        "All the realms in a compartment must have "
+                        "the same debugger visibility");
+    return false;
+  }
+
+  return true;
+}
+
 static JSObject* NewSandbox(JSContext* cx, bool lazy) {
   JS::RealmOptions options;
   SetStandardRealmOptions(options);
 
   if (defaultToSameCompartment) {
     options.creationOptions().setExistingCompartment(cx->global());
   } else {
     options.creationOptions().setNewCompartmentAndZone();
   }
 
+  JSPrincipals* principals = nullptr;
+  if (!CheckRealmOptions(cx, options, principals)) {
+    return nullptr;
+  }
+
   RootedObject obj(cx,
-                   JS_NewGlobalObject(cx, &sandbox_class, nullptr,
+                   JS_NewGlobalObject(cx, &sandbox_class, principals,
                                       JS::DontFireOnNewGlobalHook, options));
   if (!obj) {
     return nullptr;
   }
 
   {
     JSAutoRealm ar(cx, obj);
     if (!lazy && !JS::InitRealmStandardClasses(cx)) {
@@ -6269,36 +6307,18 @@ static bool NewGlobal(JSContext* cx, uns
       principals = cx->new_<ShellPrincipals>(bits);
       if (!principals) {
         return false;
       }
       JS_HoldPrincipals(principals);
     }
   }
 
-  if (creationOptions.compartmentSpecifier() ==
-      JS::CompartmentSpecifier::ExistingCompartment) {
-    JS::Compartment* comp = creationOptions.compartment();
-    bool isSystem =
-        principals && principals == cx->runtime()->trustedPrincipals();
-    if (isSystem != IsSystemCompartment(comp)) {
-      JS_ReportErrorASCII(cx,
-                          "Cannot create system and non-system realms in the "
-                          "same compartment");
-      return false;
-    }
-
-    // Debugger visibility is per-compartment, not per-realm, so make sure the
-    // requested visibility matches the existing compartment's.
-    if (creationOptions.invisibleToDebugger() != comp->invisibleToDebugger()) {
-      JS_ReportErrorASCII(cx,
-                          "All the realms in a compartment must have "
-                          "the same debugger visibility");
-      return false;
-    }
+  if (!CheckRealmOptions(cx, options, principals)) {
+    return false;
   }
 
   RootedObject global(cx, NewGlobalObject(cx, options, principals));
   if (principals) {
     JS_DropPrincipals(cx, principals);
   }
   if (!global) {
     return false;