Title: [260489] trunk
Revision
260489
Author
[email protected]
Date
2020-04-21 19:35:57 -0700 (Tue, 21 Apr 2020)

Log Message

Canonicalize JSBigInt generated by structured-cloning by calling rightTrim
https://bugs.webkit.org/show_bug.cgi?id=210816

Reviewed by Keith Miller and Darin Adler.

Source/_javascript_Core:

* runtime/JSBigInt.h:

Source/WebCore:

Let's assume that the serialized data is slightly different. JSBigInt's internal representation has various invariants. For example, if JSBigInt is zero, it should have zero length,
and its sign should be false. But there are various ways of representing zero JSBigInt in serialization format. For example, we can set sign = true, length = 0. Current code strongly
assumes that dumped data meets this JSBigInt's internal invariant. This is not good: for example, if we add a new invariant into JSBigInt, already serialized data would not meet this
invariant.
In this patch, we call `JSBigInt::rightTrim(VM&)` when finishing JSBigInt deserialization. This means that we canonicalize JSBigInt when finishing creation, and this makes this serialization
format free from JSBigInt's internal invariants. This makes JSBigInt serialization/deserialization robust. And we also add lengthInUint64 == 0 path not to call rightTrim when it is zero.
This makes deserialization robust for zero-length & signed corrupted JSBigInt zero.

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::dumpBigInt32Data):
(WebCore::CloneDeserializer::readBigInt):

LayoutTests:

Add HeapZero BigInt test.

* fast/dom/Window/window-postmessage-clone-expected.txt:
* fast/dom/Window/window-postmessage-clone.html:
* js/dom/bigint-canonicalization-in-structured-cloning-expected.txt: Added.
* js/dom/bigint-canonicalization-in-structured-cloning.html: Added.
* js/dom/script-tests/bigint-canonicalization-in-structured-cloning.js: Added.
* platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260488 => 260489)


--- trunk/LayoutTests/ChangeLog	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/LayoutTests/ChangeLog	2020-04-22 02:35:57 UTC (rev 260489)
@@ -1,3 +1,19 @@
+2020-04-21  Yusuke Suzuki  <[email protected]>
+
+        Canonicalize JSBigInt generated by structured-cloning by calling rightTrim
+        https://bugs.webkit.org/show_bug.cgi?id=210816
+
+        Reviewed by Keith Miller and Darin Adler.
+
+        Add HeapZero BigInt test.
+
+        * fast/dom/Window/window-postmessage-clone-expected.txt:
+        * fast/dom/Window/window-postmessage-clone.html:
+        * js/dom/bigint-canonicalization-in-structured-cloning-expected.txt: Added.
+        * js/dom/bigint-canonicalization-in-structured-cloning.html: Added.
+        * js/dom/script-tests/bigint-canonicalization-in-structured-cloning.js: Added.
+        * platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt:
+
 2020-04-21  Alexey Shvayka  <[email protected]>
 
         The visibilitychange event should bubble

Modified: trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt (260488 => 260489)


--- trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt	2020-04-22 02:35:57 UTC (rev 260489)
@@ -14,6 +14,7 @@
 PASS: eventData is true of type boolean
 PASS: eventData is 1 of type string
 PASS: eventData is 0 of type bigint
+PASS: eventData is 0 of type bigint
 PASS: eventData is -20 of type bigint
 PASS: eventData is 4294967295 of type bigint
 PASS: eventData is -4294967295 of type bigint

Modified: trunk/LayoutTests/fast/dom/Window/window-postmessage-clone.html (260488 => 260489)


--- trunk/LayoutTests/fast/dom/Window/window-postmessage-clone.html	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-clone.html	2020-04-22 02:35:57 UTC (rev 260489)
@@ -8,6 +8,7 @@
 <script>
 document.getElementById("description").innerHTML = "Tests that we clone object hierarchies";
 
+globalThis.heapZero = 100000000000000000000000000000000000000000n - 100000000000000000000000000000000000000000n;
 tryPostMessage('null');
 tryPostMessage('undefined');
 tryPostMessage('1');
@@ -14,6 +15,7 @@
 tryPostMessage('true');
 tryPostMessage('"1"');
 tryPostMessage('0n');
+tryPostMessage('globalThis.heapZero');
 tryPostMessage('-20n');
 tryPostMessage('4294967295n');
 tryPostMessage('-4294967295n');

Added: trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning-expected.txt (0 => 260489)


--- trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning-expected.txt	2020-04-22 02:35:57 UTC (rev 260489)
@@ -0,0 +1,12 @@
+PASS serialized.length is 26
+PASS serialized[4] is BigIntTag
+PASS result is 0n
+PASS result == 0 is true
+PASS serialized.length is 18
+PASS serialized[4] is BigIntTag
+PASS result is 0n
+PASS result == 0 is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning.html (0 => 260489)


--- trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning.html	                        (rev 0)
+++ trunk/LayoutTests/js/dom/bigint-canonicalization-in-structured-cloning.html	2020-04-22 02:35:57 UTC (rev 260489)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/dom/script-tests/bigint-canonicalization-in-structured-cloning.js (0 => 260489)


--- trunk/LayoutTests/js/dom/script-tests/bigint-canonicalization-in-structured-cloning.js	                        (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/bigint-canonicalization-in-structured-cloning.js	2020-04-22 02:35:57 UTC (rev 260489)
@@ -0,0 +1,34 @@
+// Example of the serialized data.
+// var array = new Uint8Array([
+//     7, 0, 0, 0,
+//     47, // BigInt
+//     1, // signed
+//     2, 0, 0, 0, // length
+//     0, 0, 0, 0, 0, 0, 0, 0,
+//     0, 0, 0, 0, 0, 0, 0, 0,
+// ]);
+const BigIntTag = 47;
+
+let serialized = new Uint8Array(internals.serializeObject(0xffffffffffffffffffffffffffffffffn));
+shouldBe(`serialized.length`, `26`);
+shouldBe(`serialized[4]`, `BigIntTag`);
+// Clear payload with zero.
+let offset = 4 + 1 + 1 + 4;
+for (let i = 0; i < 16; ++i) {
+    serialized[offset + i] = 0;
+}
+let result = internals.deserializeBuffer(serialized.buffer);
+shouldBe(`result`, `0n`);
+shouldBeTrue(`result == 0`);
+
+
+serialized = new Uint8Array(internals.serializeObject(0xffffffffn));
+shouldBe(`serialized.length`, `18`);
+shouldBe(`serialized[4]`, `BigIntTag`);
+// Clear payload with zero.
+for (let i = 0; i < 8; ++i) {
+    serialized[offset + i] = 0;
+}
+result = internals.deserializeBuffer(serialized.buffer);
+shouldBe(`result`, `0n`);
+shouldBeTrue(`result == 0`);

Modified: trunk/LayoutTests/platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt (260488 => 260489)


--- trunk/LayoutTests/platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/LayoutTests/platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt	2020-04-22 02:35:57 UTC (rev 260489)
@@ -10,6 +10,7 @@
 PASS: eventData is true of type boolean
 PASS: eventData is 1 of type string
 PASS: eventData is 0 of type bigint
+PASS: eventData is 0 of type bigint
 PASS: eventData is -20 of type bigint
 PASS: eventData is 4294967295 of type bigint
 PASS: eventData is -4294967295 of type bigint

Modified: trunk/Source/_javascript_Core/ChangeLog (260488 => 260489)


--- trunk/Source/_javascript_Core/ChangeLog	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-04-22 02:35:57 UTC (rev 260489)
@@ -1,3 +1,12 @@
+2020-04-21  Yusuke Suzuki  <[email protected]>
+
+        Canonicalize JSBigInt generated by structured-cloning by calling rightTrim
+        https://bugs.webkit.org/show_bug.cgi?id=210816
+
+        Reviewed by Keith Miller and Darin Adler.
+
+        * runtime/JSBigInt.h:
+
 2020-04-21  Peng Liu  <[email protected]>
 
         Fix MACCATALYST build failures

Modified: trunk/Source/_javascript_Core/runtime/JSBigInt.h (260488 => 260489)


--- trunk/Source/_javascript_Core/runtime/JSBigInt.h	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/Source/_javascript_Core/runtime/JSBigInt.h	2020-04-22 02:35:57 UTC (rev 260489)
@@ -59,7 +59,7 @@
     static size_t estimatedSize(JSCell*, VM&);
 
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
-    static JSBigInt* createZero(VM&);
+    JS_EXPORT_PRIVATE static JSBigInt* createZero(VM&);
     JS_EXPORT_PRIVATE static JSBigInt* tryCreateWithLength(JSGlobalObject*, unsigned length);
     static JSBigInt* createWithLengthUnchecked(VM&, unsigned length);
 
@@ -156,6 +156,7 @@
 
     Digit digit(unsigned);
     void setDigit(unsigned, Digit); // Use only when initializing.
+    JS_EXPORT_PRIVATE JSBigInt* rightTrim(VM&);
 
 private:
     JSBigInt(VM&, Structure*, Digit*, unsigned length);
@@ -244,7 +245,6 @@
     static JSBigInt* allocateFor(JSGlobalObject*, VM&, unsigned radix, unsigned charcount);
 
     static JSBigInt* copy(VM&, JSBigInt* x);
-    JSBigInt* rightTrim(VM&);
 
     void inplaceMultiplyAdd(Digit multiplier, Digit part);
     static JSBigInt* absoluteAdd(JSGlobalObject*, JSBigInt* x, JSBigInt* y, bool resultSign);

Modified: trunk/Source/WebCore/ChangeLog (260488 => 260489)


--- trunk/Source/WebCore/ChangeLog	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/Source/WebCore/ChangeLog	2020-04-22 02:35:57 UTC (rev 260489)
@@ -1,3 +1,22 @@
+2020-04-21  Yusuke Suzuki  <[email protected]>
+
+        Canonicalize JSBigInt generated by structured-cloning by calling rightTrim
+        https://bugs.webkit.org/show_bug.cgi?id=210816
+
+        Reviewed by Keith Miller and Darin Adler.
+
+        Let's assume that the serialized data is slightly different. JSBigInt's internal representation has various invariants. For example, if JSBigInt is zero, it should have zero length,
+        and its sign should be false. But there are various ways of representing zero JSBigInt in serialization format. For example, we can set sign = true, length = 0. Current code strongly
+        assumes that dumped data meets this JSBigInt's internal invariant. This is not good: for example, if we add a new invariant into JSBigInt, already serialized data would not meet this
+        invariant.
+        In this patch, we call `JSBigInt::rightTrim(VM&)` when finishing JSBigInt deserialization. This means that we canonicalize JSBigInt when finishing creation, and this makes this serialization
+        format free from JSBigInt's internal invariants. This makes JSBigInt serialization/deserialization robust. And we also add lengthInUint64 == 0 path not to call rightTrim when it is zero.
+        This makes deserialization robust for zero-length & signed corrupted JSBigInt zero.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::dumpBigInt32Data):
+        (WebCore::CloneDeserializer::readBigInt):
+
 2020-04-21  Peng Liu  <[email protected]>
 
         platform/mac/media/audio-session-category-audio-autoplay.html is timing out

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (260488 => 260489)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2020-04-22 02:23:06 UTC (rev 260488)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2020-04-22 02:35:57 UTC (rev 260489)
@@ -835,6 +835,10 @@
     {
         static_assert(sizeof(uint64_t) == sizeof(unsigned long long));
         write(static_cast<uint8_t>(integer < 0));
+        if (!integer) {
+            write(static_cast<uint32_t>(0)); // Length-in-uint64_t
+            return;
+        }
         write(static_cast<uint32_t>(1)); // Length-in-uint64_t
         int64_t value = static_cast<int64_t>(integer);
         if (value < 0)
@@ -2998,7 +3002,18 @@
         uint32_t lengthInUint64 = 0;
         if (!read(lengthInUint64))
             return JSValue();
+
+        if (!lengthInUint64) {
 #if USE(BIGINT32)
+            return JSValue(JSValue::JSBigInt32, 0);
+#else
+            JSBigInt* bigInt = JSBigInt::createZero(m_lexicalGlobalObject->vm());
+            m_gcBuffer.appendWithCrashOnOverflow(bigInt);
+            return bigInt;
+#endif
+        }
+
+#if USE(BIGINT32)
         static_assert(sizeof(JSBigInt::Digit) == sizeof(uint64_t));
         if (lengthInUint64 == 1) {
             static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
@@ -3020,6 +3035,7 @@
             }
             bigInt->setDigit(0, digit64);
             bigInt->setSign(sign);
+            bigInt = bigInt->rightTrim(m_lexicalGlobalObject->vm());
             m_gcBuffer.appendWithCrashOnOverflow(bigInt);
             return bigInt;
         }
@@ -3055,6 +3071,7 @@
             }
         }
         bigInt->setSign(sign);
+        bigInt = bigInt->rightTrim(m_lexicalGlobalObject->vm());
         m_gcBuffer.appendWithCrashOnOverflow(bigInt);
         return bigInt;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to