Bug 1583251 - P5 - Having some js tests to verify the deserialize function; r=nika,lth
☠☠ backed out by 53bf396c988d ☠ ☠
authorTom Tung <ttung@mozilla.com>
Tue, 15 Oct 2019 11:12:38 +0000
changeset 498143 bfe390ad771b5bbaa5515e376dac91373c7837bd
parent 498142 0113c698b44d431fe02d3f73bea90d65e69df76b
child 498144 4c43b1c81af598a2dc2a11abf91214360d03c300
push id98311
push userttung@mozilla.com
push dateFri, 18 Oct 2019 13:44:19 +0000
treeherderautoland@bfe390ad771b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika, lth
bugs1583251
milestone71.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 1583251 - P5 - Having some js tests to verify the deserialize function; r=nika,lth Depends on D48560 Differential Revision: https://phabricator.services.mozilla.com/D48561
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/wasm/memory-cloning.js
js/src/tests/non262/extensions/clone-sab.js
js/src/tests/non262/extensions/sharedtypedarray.js
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -3442,26 +3442,51 @@ static bool Deserialize(JSContext* cx, u
 
   if (!args.get(0).isObject() || !args[0].toObject().is<CloneBufferObject>()) {
     JS_ReportErrorASCII(cx, "deserialize requires a clonebuffer argument");
     return false;
   }
   Rooted<CloneBufferObject*> obj(cx,
                                  &args[0].toObject().as<CloneBufferObject>());
 
+  JS::CloneDataPolicy policy;
   JS::StructuredCloneScope scope =
       obj->isSynthetic() ? JS::StructuredCloneScope::DifferentProcess
                          : JS::StructuredCloneScope::SameProcessSameThread;
   if (args.get(1).isObject()) {
     RootedObject opts(cx, &args[1].toObject());
     if (!opts) {
       return false;
     }
 
     RootedValue v(cx);
+    if (!JS_GetProperty(cx, opts, "SharedArrayBuffer", &v)) {
+      return false;
+    }
+
+    if (!v.isUndefined()) {
+      JSString* str = JS::ToString(cx, v);
+      if (!str) {
+        return false;
+      }
+      JSLinearString* poli = str->ensureLinear(cx);
+      if (!poli) {
+        return false;
+      }
+
+      if (StringEqualsLiteral(poli, "allow")) {
+        policy.allowSharedMemory();
+      } else if (StringEqualsLiteral(poli, "deny")) {
+        // default
+      } else {
+        JS_ReportErrorASCII(cx, "Invalid policy value for 'SharedArrayBuffer'");
+        return false;
+      }
+    }
+
     if (!JS_GetProperty(cx, opts, "scope", &v)) {
       return false;
     }
 
     if (!v.isUndefined()) {
       RootedString str(cx, JS::ToString(cx, v));
       if (!str) {
         return false;
@@ -3493,18 +3518,17 @@ static bool Deserialize(JSContext* cx, u
 
   bool hasTransferable;
   if (!JS_StructuredCloneHasTransferables(*obj->data(), &hasTransferable)) {
     return false;
   }
 
   RootedValue deserialized(cx);
   if (!JS_ReadStructuredClone(cx, *obj->data(), JS_STRUCTURED_CLONE_VERSION,
-                              scope, &deserialized, JS::CloneDataPolicy(),
-                              nullptr, nullptr)) {
+                              scope, &deserialized, policy, nullptr, nullptr)) {
     return false;
   }
   args.rval().set(deserialized);
 
   // Consume any clone buffer with transferables; throw an error if it is
   // deserialized again.
   if (hasTransferable) {
     obj->discard();
@@ -6668,18 +6692,21 @@ gc::ZealModeHelpText),
 "      DifferentProcess, or DifferentProcessForIndexedDB. Determines how some\n"
 "      values will be serialized. Clone buffers may only be deserialized with a\n"
 "      compatible scope. NOTE - For DifferentProcess/DifferentProcessForIndexedDB,\n"
 "      must also set SharedArrayBuffer:'deny' if data contains any shared memory\n"
 "      object."),
 
     JS_FN_HELP("deserialize", Deserialize, 1, 0,
 "deserialize(clonebuffer[, opts])",
-"  Deserialize data generated by serialize. 'opts' is an options hash with one\n"
-"  recognized key 'scope', which limits the clone buffers that are considered\n"
+"  Deserialize data generated by serialize. 'opts' may be an options hash.\n"
+"  Valid keys:\n"
+"    'SharedArrayBuffer' - either 'allow' or 'deny' (the default)\n"
+"      to specify whether SharedArrayBuffers may be serialized.\n"
+"    'scope', which limits the clone buffers that are considered\n"
 "  valid. Allowed values: 'SameProcessSameThread', 'SameProcessDifferentThread',\n"
 "  'DifferentProcess', and 'DifferentProcessForIndexedDB'. So for example, a\n"
 "  DifferentProcessForIndexedDB clone buffer may be deserialized in any scope, but\n"
 "  a SameProcessSameThread clone buffer cannot be deserialized in a\n"
 "  DifferentProcess scope."),
 
     JS_FN_HELP("detachArrayBuffer", DetachArrayBuffer, 1, 0,
 "detachArrayBuffer(buffer)",
--- a/js/src/jit-test/tests/wasm/memory-cloning.js
+++ b/js/src/jit-test/tests/wasm/memory-cloning.js
@@ -19,17 +19,17 @@
 // observe shared effects.
 
 {
     let mem1 = new WebAssembly.Memory({initial: 2, maximum: 4, shared: true});
     let buf1 = mem1.buffer;
 
     // Serialization and deserialization of shared memories work:
 
-    let mem2 = deserialize(serialize(mem1, [], {SharedArrayBuffer: 'allow'}));
+    let mem2 = deserialize(serialize(mem1, [], {SharedArrayBuffer: 'allow'}), {SharedArrayBuffer: 'allow'});
     assertEq(mem2 instanceof WebAssembly.Memory, true);
     let buf2 = mem2.buffer;
     assertEq(buf2 instanceof SharedArrayBuffer, true);
 
     assertEq(buf1 !== buf2, true);
     assertEq(buf1.byteLength, buf2.byteLength);
 
     // Effects to one buffer must be reflected in the other:
@@ -76,11 +76,11 @@
 // of the SAB should not change even if the memory was grown after serialization
 // and before deserialization.
 
 {
     let mem = new WebAssembly.Memory({initial: 2, maximum: 4, shared: true});
     let buf = mem.buffer;
     let clonedbuf = serialize(buf, [], {SharedArrayBuffer: 'allow'});
     mem.grow(1);
-    let buf2 = deserialize(clonedbuf);
+    let buf2 = deserialize(clonedbuf, {SharedArrayBuffer: 'allow'});
     assertEq(buf.byteLength, buf2.byteLength);
 }
--- a/js/src/tests/non262/extensions/clone-sab.js
+++ b/js/src/tests/non262/extensions/clone-sab.js
@@ -17,15 +17,15 @@ if (!this.SharedArrayBuffer) {
 let x = new SharedArrayBuffer(1);
 let y = serialize(x, [], {SharedArrayBuffer: 'allow'});
 x = null;
 
 // If the bug is present this loop usually crashes quickly during
 // deserialization because the memory has become unmapped.
 
 for (let i=0 ; i < 50 ; i++ ) {
-    let obj = deserialize(y);
+    let obj = deserialize(y, {SharedArrayBuffer: 'allow'});
     let z = new Int8Array(obj);
     z[0] = 0;
 }
 
 reportCompare(true, true);
 
--- a/js/src/tests/non262/extensions/sharedtypedarray.js
+++ b/js/src/tests/non262/extensions/sharedtypedarray.js
@@ -165,26 +165,26 @@ function testSharedTypedArrayMethods() {
     assertEq(v[7], -2);
     assertEq(v[8], -4);
     assertEq(v[9], -5);
 }
 
 function testClone1() {
     var sab1 = b;
     var blob = serialize(sab1, [], {SharedArrayBuffer: 'allow'});
-    var sab2 = deserialize(blob);
+    var sab2 = deserialize(blob, {SharedArrayBuffer: 'allow'});
     if (typeof sharedAddress != "undefined")
 	assertEq(sharedAddress(sab1), sharedAddress(sab2));
 }
 
 function testClone2() {
     var sab = b;
     var ia1 = new Int32Array(sab);
     var blob = serialize(ia1, [], {SharedArrayBuffer: 'allow'});
-    var ia2 = deserialize(blob);
+    var ia2 = deserialize(blob, {SharedArrayBuffer: 'allow'});
     assertEq(ia1.length, ia2.length);
     assertEq(ia1.buffer instanceof SharedArrayBuffer, true);
     if (typeof sharedAddress != "undefined")
 	assertEq(sharedAddress(ia1.buffer), sharedAddress(ia2.buffer));
     ia1[10] = 37;
     assertEq(ia2[10], 37);
 }
 
@@ -198,16 +198,29 @@ function testNoClone() {
     // This tests the actual cloning functionality - should fail
     assertThrowsInstanceOf(() => serialize(b, [], {SharedArrayBuffer: 'deny'}), TypeError);
 
     // This tests that cloning a SharedArrayBuffer is not allowed by default
     assertThrowsInstanceOf(() => serialize(b), TypeError);
 
     // Ditto - should succeed
     assertEq(typeof serialize(b, [], {SharedArrayBuffer: 'allow'}), "object");
+
+    let blob = serialize(b, [], {SharedArrayBuffer: 'allow'});
+    // This just tests the API in deserialize()
+    assertThrowsInstanceOf(() => deserialize(blob, {SharedArrayBuffer: false}), Error);
+
+    // This tests the actual cloning functionality - should fail
+    assertThrowsInstanceOf(() => deserialize(blob, {SharedArrayBuffer: 'deny'}), TypeError);
+
+    // This tests that cloning a SharedArrayBuffer is not allowed by default
+    assertThrowsInstanceOf(() => deserialize(blob), TypeError);
+
+    // Ditto - should succeed
+    assertEq(typeof deserialize(blob, {SharedArrayBuffer: 'allow'}), "object");
 }
 
 function testRedundantTransfer() {
     // Throws TypeError in the shell, DataCloneError in the browser.
     assertThrowsInstanceOf(() => {
 	var sab1 = b;
 	var blob = serialize(sab1, [sab1], {SharedArrayBuffer: 'allow'});
     }, TypeError);