Title: [118955] trunk
Revision
118955
Author
[email protected]
Date
2012-05-30 12:44:22 -0700 (Wed, 30 May 2012)

Log Message

[v8] Crash after redefining setter on typed array to a number
https://bugs.webkit.org/show_bug.cgi?id=87862

Patch by Ulan Degenbaev <[email protected]> on 2012-05-30
Reviewed by Kenneth Russell.

Remove calls to typed array set() method from C++.
Store the copying script as a hidden property of a typed array prototype.

Source/WebCore:

Test: fast/canvas/webgl/array-override-set.html

* bindings/v8/custom/V8ArrayBufferViewCustom.cpp:
(WebCore):
(WebCore::getHiddenCopyMethod):
(WebCore::installHiddenCopyMethod):
(WebCore::copyElements):
* bindings/v8/custom/V8ArrayBufferViewCustom.h:
(WebCore):
(WebCore::constructWebGLArray):
(WebCore::setWebGLArrayHelper):
* bindings/v8/custom/V8ArrayBufferViewCustomScript.js:

LayoutTests:

* fast/canvas/webgl/array-override-set-expected.txt: Added.
* fast/canvas/webgl/array-override-set.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (118954 => 118955)


--- trunk/LayoutTests/ChangeLog	2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/LayoutTests/ChangeLog	2012-05-30 19:44:22 UTC (rev 118955)
@@ -1,3 +1,16 @@
+2012-05-30  Ulan Degenbaev  <[email protected]>
+
+        [v8] Crash after redefining setter on typed array to a number
+        https://bugs.webkit.org/show_bug.cgi?id=87862
+
+        Reviewed by Kenneth Russell.
+
+        Remove calls to typed array set() method from C++.
+        Store the copying script as a hidden property of a typed array prototype.
+
+        * fast/canvas/webgl/array-override-set-expected.txt: Added.
+        * fast/canvas/webgl/array-override-set.html: Added.
+
 2012-05-30  Stephen Chenney  <[email protected]>
 
         http/tests/cache/subresource-expiration-2.html is slow on Linux

Added: trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt (0 => 118955)


--- trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-override-set-expected.txt	2012-05-30 19:44:22 UTC (rev 118955)
@@ -0,0 +1,27 @@
+Test overriding the set method of WebGL array
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+Regression test for ????
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS array[0] is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/canvas/webgl/array-override-set.html (0 => 118955)


--- trunk/LayoutTests/fast/canvas/webgl/array-override-set.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/array-override-set.html	2012-05-30 19:44:22 UTC (rev 118955)
@@ -0,0 +1,47 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Test overriding the set method of WebGL array");
+
+debug('Regression test for ????');
+
+var array;
+var typeNames = ['Float32Array', 'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array',
+                 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array']
+
+function overrideSetWithNumberAndConstruct(typeName) {
+  var type = window[typeName];
+  type.prototype.set = 0x3ffff;
+  array = new type([0], function() {});
+  shouldBe("array[0]", "0");
+}
+
+for (var i = 0; i < typeNames.length; i++) {
+  overrideSetWithNumberAndConstruct(typeNames[i]);
+}
+
+function overrideSetWithNumberAndSet(typeName) {
+  var type = window[typeName];
+  array = new type(10);
+  type.prototype.set = 0x3ffff;
+  array[0] = 8;
+  array.set([0], function() {});
+  shouldBe("array[0]", "0");
+}
+
+for (var i = 0; i < typeNames.length; i++) {
+  overrideSetWithNumberAndConstruct(typeNames[i]);
+}
+
+</script>
+
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (118954 => 118955)


--- trunk/Source/WebCore/ChangeLog	2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/ChangeLog	2012-05-30 19:44:22 UTC (rev 118955)
@@ -1,3 +1,26 @@
+2012-05-30  Ulan Degenbaev  <[email protected]>
+
+        [v8] Crash after redefining setter on typed array to a number
+        https://bugs.webkit.org/show_bug.cgi?id=87862
+
+        Reviewed by Kenneth Russell.
+
+        Remove calls to typed array set() method from C++.
+        Store the copying script as a hidden property of a typed array prototype.
+
+        Test: fast/canvas/webgl/array-override-set.html
+
+        * bindings/v8/custom/V8ArrayBufferViewCustom.cpp:
+        (WebCore):
+        (WebCore::getHiddenCopyMethod):
+        (WebCore::installHiddenCopyMethod):
+        (WebCore::copyElements):
+        * bindings/v8/custom/V8ArrayBufferViewCustom.h:
+        (WebCore):
+        (WebCore::constructWebGLArray):
+        (WebCore::setWebGLArrayHelper):
+        * bindings/v8/custom/V8ArrayBufferViewCustomScript.js:
+
 2012-05-30  David Hyatt  <[email protected]>
 
         https://bugs.webkit.org/show_bug.cgi?id=87882

Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp (118954 => 118955)


--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp	2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.cpp	2012-05-30 19:44:22 UTC (rev 118955)
@@ -27,51 +27,51 @@
 #include "V8ArrayBufferViewCustom.h"
 
 #include "V8ArrayBufferViewCustomScript.h"
+
 #include <v8.h>
 
 
 namespace WebCore {
 
 // The random suffix helps to avoid name collision.
-const char fastSetFlagName[] = "TypedArray::FastSet::8NkZVq";
+const char hiddenCopyMethodName[] = "TypedArray::HiddenCopy::8NkZVq";
 
-bool fastSetInstalled(v8::Handle<v8::Object> array)
+v8::Handle<v8::Value> getHiddenCopyMethod(v8::Handle<v8::Object> prototype)
 {
-    // Use a hidden flag in the global object an indicator of whether the fast
-    // 'set' is installed or not.
-    v8::Handle<v8::Object> global = array->CreationContext()->Global();
-    v8::Handle<v8::String> key = v8::String::New(fastSetFlagName);
-    v8::Handle<v8::Value> fastSetFlag = global->GetHiddenValue(key);
-    return !fastSetFlag.IsEmpty();
+    v8::Handle<v8::String> key = v8::String::New(hiddenCopyMethodName);
+    return prototype->GetHiddenValue(key);
 }
 
-void installFastSet(v8::Handle<v8::Object> array)
-{
+v8::Handle<v8::Value> installHiddenCopyMethod(v8::Handle<v8::Object> prototype) {
     v8::TryCatch tryCatch;
     tryCatch.SetVerbose(true);
-    v8::Handle<v8::Object> global = array->CreationContext()->Global();
-    v8::Handle<v8::String> key = v8::String::New(fastSetFlagName);
-    global->SetHiddenValue(key, v8::Boolean::New(true));
-
     String source(reinterpret_cast<const char*>(V8ArrayBufferViewCustomScript_js),
                   sizeof(V8ArrayBufferViewCustomScript_js));
     v8::Handle<v8::Script> script = v8::Script::Compile(v8String(source));
-    script->Run();
+    v8::Handle<v8::Value> value = script->Run();
+    v8::Handle<v8::String> key = v8::String::New(hiddenCopyMethodName);
+    prototype->SetHiddenValue(key, value);
+    return value;
 }
 
-
-void copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t offset)
+bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t length, uint32_t offset)
 {
-    v8::Handle<v8::String> key = v8::String::New("set");
-    v8::Handle<v8::Function> set = destArray->Get(key).As<v8::Function>();
-    v8::Handle<v8::Value> arguments[2];
-    int numberOfArguments = 1;
+    v8::Handle<v8::Value> prototype_value = destArray->GetPrototype();
+    if (prototype_value.IsEmpty() || !prototype_value->IsObject())
+        return false;
+    v8::Handle<v8::Object> prototype = prototype_value.As<v8::Object>();
+    v8::Handle<v8::Value> value = getHiddenCopyMethod(prototype);
+    if (value.IsEmpty())
+        value = installHiddenCopyMethod(prototype);
+    if (value.IsEmpty() || !value->IsFunction())
+        return false;
+    v8::Handle<v8::Function> copy_method = value.As<v8::Function>();
+    v8::Handle<v8::Value> arguments[3];
     arguments[0] = srcArray;
-    if (offset) {
-        arguments[1] = v8::Uint32::New(offset);
-        numberOfArguments = 2;
-    }
-    set->Call(destArray, numberOfArguments, arguments);
+    arguments[1] = v8::Uint32::New(length);
+    arguments[2] = v8::Uint32::New(offset);
+    copy_method->Call(destArray, 3, arguments);
+    return true;
 }
 
 }

Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h (118954 => 118955)


--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h	2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustom.h	2012-05-30 19:44:22 UTC (rev 118955)
@@ -40,20 +40,11 @@
 
 namespace WebCore {
 
+// Copy the elements from the source array to the typed destination array.
+// Returns true if it succeeded, otherwise returns false.
+bool copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t length, uint32_t offset);
 
-// Check if the _javascript_ 'set' method was already installed
-// on the prototype of the given typed array.
-bool fastSetInstalled(v8::Handle<v8::Object> array);
 
-// Install the _javascript_ 'set' method on the prototype of
-// the given typed array.
-void installFastSet(v8::Handle<v8::Object> array);
-
-// Copy the elements from the source array to the typed destination array by
-// invoking the 'set' method of the destination array in JS.
-void copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t offset);
-
-
 // Template function used by the ArrayBufferView*Constructor callbacks.
 template<class ArrayClass, class ElementType>
 v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool hasIndexer)
@@ -173,8 +164,13 @@
     V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get());
     args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length());
 
-    if (!srcArray.IsEmpty())
-        copyElements(args.Holder(), srcArray, 0);
+    if (!srcArray.IsEmpty()) {
+        bool copied = copyElements(args.Holder(), srcArray, len, 0);
+        if (!copied) {
+            for (unsigned i = 0; i < len; i++)
+                array->set(i, srcArray->Get(i)->NumberValue());
+        }
+    }
 
     v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::New(args.Holder());
     wrapper.MarkIndependent();
@@ -214,11 +210,8 @@
             // Out of range offset or overflow
             return V8Proxy::setDOMException(INDEX_SIZE_ERR, args.GetIsolate());
         }
-
-        if (!fastSetInstalled(args.Holder())) {
-            installFastSet(args.Holder());
-            copyElements(args.Holder(), array, offset);
-        } else {
+        bool copied = copyElements(args.Holder(), array, length, offset);
+        if (!copied) {
             for (uint32_t i = 0; i < length; i++)
                 impl->set(offset + i, array->Get(i)->NumberValue());
         }

Modified: trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js (118954 => 118955)


--- trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js	2012-05-30 19:40:29 UTC (rev 118954)
+++ trunk/Source/WebCore/bindings/v8/custom/V8ArrayBufferViewCustomScript.js	2012-05-30 19:44:22 UTC (rev 118955)
@@ -23,42 +23,14 @@
  */
 
 (function() {
-
-var optimizeSetMethod = function(type)
-{
-    if (typeof type === 'function' &&
-        typeof type.prototype !== 'undefined' && 
-        typeof type.prototype.set === 'function') {
-        type.prototype.set = (function() {
-            var nativeSet = type.prototype.set;
-            var f = function(source, offset)
-            {
-                if (source.constructor === Array) {
-                    var length = source.length;
-                    offset = offset || 0;
-                    if (offset < 0 || offset + length > this.length) {
-                        return nativeSet.call(this, source, offset);
-                    }
-                    for (var i = 0; i < length; i++)
-                        this[i + offset] = source[i];
-                } else
-                    return nativeSet.call(this, source, offset);
-            }
-            f.name = "set";
-            return f;
-        })();
+    return function(source, length, offset) {
+        if (offset == 0) {
+            for (var i = 0; i < length; i++)
+                this[i] = source[i];
+        } else {
+            for (var i = 0; i < length; i++)
+                this[i + offset] = source[i];
+        }
     }
-};
-
-optimizeSetMethod(Float32Array);
-optimizeSetMethod(Float64Array);
-optimizeSetMethod(Int8Array);
-optimizeSetMethod(Int16Array);
-optimizeSetMethod(Int32Array);
-optimizeSetMethod(Uint8Array);
-optimizeSetMethod(Uint8ClampedArray);
-optimizeSetMethod(Uint16Array);
-optimizeSetMethod(Uint32Array);
-
 })();
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to