Title: [113233] trunk
Revision
113233
Author
dslo...@google.com
Date
2012-04-04 13:43:31 -0700 (Wed, 04 Apr 2012)

Log Message

Source/WebCore: [JSC] ArrayBufferView and its ArrayBuffer are appended to object pool in wrong order
https://bugs.webkit.org/show_bug.cgi?id=82090
The implementation of structured cloning algorithm (http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm)
in SerializedScriptValue.cpp assigns numerical identifiers to encontered objects as it traverses
the cloned object during serialization.
When the cloning encounters an already seen object, it transfers the assigned numerical id
instead of cloning the object again. Deserialization process then repeats the process in
the mirror fashion, i.e. on deserializing the object it assigns deserialized object a numeric id and if it
deserializes the id it substitutes the perviously deserialized objects. It is critical that serialization and deserialization
assigns numeric ids in the same order.

The bug (discovered by Yong Li) is that when serializing ArrayBufferView, the ids were assigned first to
the ArrayBufferView and then to underlying ArrayBuffer; however on deserialization the ids were assigned another way round.

This patch fixes that by assigning the id first to ArrayBuffer and then to ArrayBufferView, and adds corresponding test cases.

Reviewed by Kenneth Russell.

New test cases added to fast/canvas/web-gl/array-message-passing.html.

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::checkForDuplicate):
(CloneSerializer):
(WebCore::CloneSerializer::recordObject):
(WebCore::CloneSerializer::startObjectInternal):
(WebCore::CloneSerializer::dumpIfTerminal):

LayoutTests: [JSC] ArrayBufferView and its ArrayBuffer are appended to object pool in wrong order
https://bugs.webkit.org/show_bug.cgi?id=82090
Adds tests that cover more than one view of the same ArrayBuffer being cloned.

Reviewed by Kenneth Russell.

* fast/canvas/webgl/array-message-passing-expected.txt:
* fast/canvas/webgl/script-tests/array-message-passing.js:
(typedArrayCompare):
(dataViewCompare):
(dataViewCompare2):
(dataViewCompare3):

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (113232 => 113233)


--- trunk/LayoutTests/ChangeLog	2012-04-04 20:31:24 UTC (rev 113232)
+++ trunk/LayoutTests/ChangeLog	2012-04-04 20:43:31 UTC (rev 113233)
@@ -1,3 +1,18 @@
+2012-04-04  Dmitry Lomov  <dslo...@google.com>
+
+        [JSC] ArrayBufferView and its ArrayBuffer are appended to object pool in wrong order
+        https://bugs.webkit.org/show_bug.cgi?id=82090
+        Adds tests that cover more than one view of the same ArrayBuffer being cloned.
+
+        Reviewed by Kenneth Russell.
+
+        * fast/canvas/webgl/array-message-passing-expected.txt:
+        * fast/canvas/webgl/script-tests/array-message-passing.js:
+        (typedArrayCompare):
+        (dataViewCompare):
+        (dataViewCompare2):
+        (dataViewCompare3):
+
 2012-04-04  Adam Klein  <ad...@chromium.org>
 
         Web Inspector: break on DOM node insertion only once per operation, not once per inserted node

Modified: trunk/LayoutTests/fast/canvas/webgl/array-message-passing-expected.txt (113232 => 113233)


--- trunk/LayoutTests/fast/canvas/webgl/array-message-passing-expected.txt	2012-04-04 20:31:24 UTC (rev 113232)
+++ trunk/LayoutTests/fast/canvas/webgl/array-message-passing-expected.txt	2012-04-04 20:43:31 UTC (rev 113233)
@@ -23,6 +23,30 @@
 PASS DataView1: buffers have the same contents
 PASS DataView1: offset is 0
 PASS DataView1: length is 1
+PASS DataView1-dup: classes are [object DataView]
+PASS DataView1-dup: classes are [object ArrayBuffer]
+PASS DataView1-dup: buffer lengths are 1
+PASS DataView1-dup: buffers have the same contents
+PASS DataView1-dup: offset is 0
+PASS DataView1-dup: length is 1
+PASS DataView1-dup: classes are [object DataView]
+PASS DataView1-dup: classes are [object ArrayBuffer]
+PASS DataView1-dup: buffer lengths are 1
+PASS DataView1-dup: buffers have the same contents
+PASS DataView1-dup: offset is 0
+PASS DataView1-dup: length is 1
+PASS DataView1-dup2: classes are [object DataView]
+PASS DataView1-dup2: classes are [object ArrayBuffer]
+PASS DataView1-dup2: buffer lengths are 1
+PASS DataView1-dup2: buffers have the same contents
+PASS DataView1-dup2: offset is 0
+PASS DataView1-dup2: length is 1
+PASS DataView1-dup2: classes are [object DataView]
+PASS DataView1-dup2: classes are [object ArrayBuffer]
+PASS DataView1-dup2: buffer lengths are 1
+PASS DataView1-dup2: buffers have the same contents
+PASS DataView1-dup2: offset is 0
+PASS DataView1-dup2: length is 1
 PASS DataView128: classes are [object DataView]
 PASS DataView128: classes are [object ArrayBuffer]
 PASS DataView128: buffer lengths are 128

Modified: trunk/LayoutTests/fast/canvas/webgl/script-tests/array-message-passing.js (113232 => 113233)


--- trunk/LayoutTests/fast/canvas/webgl/script-tests/array-message-passing.js	2012-04-04 20:31:24 UTC (rev 113232)
+++ trunk/LayoutTests/fast/canvas/webgl/script-tests/array-message-passing.js	2012-04-04 20:43:31 UTC (rev 113233)
@@ -69,14 +69,43 @@
         testFailed(testName + ": expected BYTES_PER_ELEMENT " + sent.BYTES_PER_ELEMENT + ", saw " + got.BYTES_PER_ELEMENT);
         return false;
     }
+    return true;
 }
 
 function dataViewCompare(testName, got, sent) {
-    if (!viewCompare(testName, got, sent)) {
+    return viewCompare(testName, got, sent);
+}
+
+function dataViewCompare2(testName, got, sent) {
+    for (var i = 0; i < 2; ++i) {
+        if (!dataViewCompare(testName, got[i], sent[i])) {
+            return false;
+        }
+    }
+    if (got[0].buffer !== got[1].buffer) {
+        testFailed(testName + ": expected the same ArrayBuffer for both views");
         return false;
     }
+    return true;
 }
+function dataViewCompare3(testName, got, sent) {
+    for (var i = 0; i < 3; i += 2) {
+        if (!dataViewCompare(testName, got[i], sent[i])) {
+            return false;
+        }
+    }
+    if (got[1].x !== sent[1].x || got[1].y !== sent[1].y) {
+        testFailed(testName + ": {x:1, y:1} was not transferred properly");
+        return false;
+    }
+    if (got[0].buffer !== got[2].buffer) {
+        testFailed(testName + ": expected the same ArrayBuffer for both views");
+        return false;
+    }
+    return false;
+}
 
+
 function createBuffer(length) {
     var buffer = new ArrayBuffer(length);
     var view = new Uint8Array(buffer);
@@ -115,12 +144,16 @@
     ["Float64", Float64Array, 8]
 ];
 
+var arrayBuffer1 = createBuffer(1);
+
 var testList = [
     ['ArrayBuffer0', new ArrayBuffer(0), bufferCompare],
     ['ArrayBuffer1', createBuffer(1), bufferCompare],
     ['ArrayBuffer128', createBuffer(128), bufferCompare],
     ['DataView0', new DataView(new ArrayBuffer(0)), dataViewCompare],
     ['DataView1', new DataView(createBuffer(1)), dataViewCompare],
+    ['DataView1-dup', [new DataView(arrayBuffer1), new DataView(arrayBuffer1)], dataViewCompare2],
+    ['DataView1-dup2', [new DataView(arrayBuffer1), {x:1, y:1}, new DataView(arrayBuffer1)], dataViewCompare3],
     ['DataView128', new DataView(createBuffer(128)), dataViewCompare],
     ['DataView1_offset_at_end', new DataView(createBuffer(1), 1, 0), dataViewCompare],
     ['DataView128_offset_at_end', new DataView(createBuffer(128), 128, 0), dataViewCompare],

Modified: trunk/Source/WebCore/ChangeLog (113232 => 113233)


--- trunk/Source/WebCore/ChangeLog	2012-04-04 20:31:24 UTC (rev 113232)
+++ trunk/Source/WebCore/ChangeLog	2012-04-04 20:43:31 UTC (rev 113233)
@@ -1,3 +1,32 @@
+2012-04-04  Dmitry Lomov  <dslo...@google.com>
+
+        [JSC] ArrayBufferView and its ArrayBuffer are appended to object pool in wrong order
+        https://bugs.webkit.org/show_bug.cgi?id=82090
+        The implementation of structured cloning algorithm (http://www.w3.org/TR/html5/common-dom-interfaces.html#internal-structured-cloning-algorithm)
+        in SerializedScriptValue.cpp assigns numerical identifiers to encontered objects as it traverses
+        the cloned object during serialization.
+        When the cloning encounters an already seen object, it transfers the assigned numerical id
+        instead of cloning the object again. Deserialization process then repeats the process in 
+        the mirror fashion, i.e. on deserializing the object it assigns deserialized object a numeric id and if it
+        deserializes the id it substitutes the perviously deserialized objects. It is critical that serialization and deserialization
+        assigns numeric ids in the same order.
+
+        The bug (discovered by Yong Li) is that when serializing ArrayBufferView, the ids were assigned first to 
+        the ArrayBufferView and then to underlying ArrayBuffer; however on deserialization the ids were assigned another way round.
+
+        This patch fixes that by assigning the id first to ArrayBuffer and then to ArrayBufferView, and adds corresponding test cases.
+
+        Reviewed by Kenneth Russell.
+
+        New test cases added to fast/canvas/web-gl/array-message-passing.html.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::checkForDuplicate):
+        (CloneSerializer):
+        (WebCore::CloneSerializer::recordObject):
+        (WebCore::CloneSerializer::startObjectInternal):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+
 2012-04-04  Ian Vollick  <voll...@chromium.org>
 
         [chromium] When setting animation started events, should check the root layer

Modified: trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp (113232 => 113233)


--- trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2012-04-04 20:31:24 UTC (rev 113232)
+++ trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp	2012-04-04 20:43:31 UTC (rev 113233)
@@ -389,20 +389,33 @@
         return isJSArray(object) || object->inherits(&JSArray::s_info);
     }
 
-    bool startObjectInternal(JSObject* object)
+    bool checkForDuplicate(JSObject* object)
     {
         // Record object for graph reconstruction
         ObjectPool::AddResult addResult = m_objectPool.add(object, m_objectPool.size());
-        
+
         // Handle duplicate references
         if (!addResult.isNewEntry) {
             write(ObjectReferenceTag);
             ASSERT(static_cast<int32_t>(addResult.iterator->second) < m_objectPool.size());
             writeObjectIndex(addResult.iterator->second);
-            return false;
+            return true;
         }
-        
+
+        return false;
+    }
+
+    void recordObject(JSObject* object)
+    {
+        m_objectPool.add(object, m_objectPool.size());
         m_gcBuffer.append(object);
+    }
+
+    bool startObjectInternal(JSObject* object)
+    {
+        if (checkForDuplicate(object))
+            return false;
+        recordObject(object);
         return true;
     }
 
@@ -643,9 +656,11 @@
                 return true;
             }
             if (obj->inherits(&JSArrayBufferView::s_info)) {
-                if (!startObjectInternal(obj))
+                if (checkForDuplicate(obj))
                     return true;
-                return dumpArrayBufferView(obj, code);
+                bool success = dumpArrayBufferView(obj, code);
+                recordObject(obj);
+                return success;
             }
 
             CallData unusedData;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to