Bug 1583251 - P5 - Having some js tests to verify the deserialize function; r=nika,lth
authorTom Tung <ttung@mozilla.com>
Wed, 23 Oct 2019 07:20:52 +0000
changeset 498678 6145f7c31786ebb18ebd6af87c5197a4c697d5ac
parent 498677 481515dd4b9d31d5ae7d934935e5262093a60a2a
child 498679 058946a415aa57838bbd953d082bae9801d4474e
push id98599
push userttung@mozilla.com
push dateWed, 23 Oct 2019 07:22:53 +0000
treeherderautoland@058946a415aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnika, lth
bugs1583251
milestone72.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 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);