Title: [203087] trunk/Source/_javascript_Core
Revision
203087
Author
sbar...@apple.com
Date
2016-07-11 15:08:40 -0700 (Mon, 11 Jul 2016)

Log Message

some paths in Array.prototype.splice don't account for the array not having certain indexed properties
https://bugs.webkit.org/show_bug.cgi?id=159641
<rdar://problem/27171999>

Reviewed by Filip Pizlo and Keith Miller.

Array.prototype.splice was incorrectly putting properties on
the result array even if the |this| array didn't have those
properties. This is not the behavior of the spec. However, this
could also cause a crash because we can construct a program where
we would putByIndex on a typed array where the value we are
putting is JSValue(). This is bad because the typed array will
try to convert JSValue() into an integer.

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncSplice):
* tests/stress/array-prototype-splice-making-typed-array.js: Added.
(assert):
(test):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (203086 => 203087)


--- trunk/Source/_javascript_Core/ChangeLog	2016-07-11 22:02:38 UTC (rev 203086)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-07-11 22:08:40 UTC (rev 203087)
@@ -1,3 +1,25 @@
+2016-07-11  Saam Barati  <sbar...@apple.com>
+
+        some paths in Array.prototype.splice don't account for the array not having certain indexed properties
+        https://bugs.webkit.org/show_bug.cgi?id=159641
+        <rdar://problem/27171999>
+
+        Reviewed by Filip Pizlo and Keith Miller.
+
+        Array.prototype.splice was incorrectly putting properties on
+        the result array even if the |this| array didn't have those
+        properties. This is not the behavior of the spec. However, this
+        could also cause a crash because we can construct a program where
+        we would putByIndex on a typed array where the value we are
+        putting is JSValue(). This is bad because the typed array will
+        try to convert JSValue() into an integer.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoFuncSplice):
+        * tests/stress/array-prototype-splice-making-typed-array.js: Added.
+        (assert):
+        (test):
+
 2016-07-11  Mark Lam  <mark....@apple.com>
 
         Refactor JSStack to only be the stack data structure for the C Loop.

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (203086 => 203087)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-07-11 22:02:38 UTC (rev 203086)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-07-11 22:08:40 UTC (rev 203087)
@@ -885,6 +885,8 @@
                 JSValue v = getProperty(exec, thisObj, k + begin);
                 if (UNLIKELY(vm.exception()))
                     return JSValue::encode(jsUndefined());
+                if (UNLIKELY(!v))
+                    continue;
                 result->putByIndexInline(exec, k, v, true);
                 if (UNLIKELY(vm.exception()))
                     return JSValue::encode(jsUndefined());
@@ -898,6 +900,8 @@
                 JSValue v = getProperty(exec, thisObj, k + begin);
                 if (UNLIKELY(vm.exception()))
                     return JSValue::encode(jsUndefined());
+                if (UNLIKELY(!v))
+                    continue;
                 result->initializeIndex(vm, k, v);
             }
         }

Added: trunk/Source/_javascript_Core/tests/stress/array-prototype-splice-making-typed-array.js (0 => 203087)


--- trunk/Source/_javascript_Core/tests/stress/array-prototype-splice-making-typed-array.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/array-prototype-splice-making-typed-array.js	2016-07-11 22:08:40 UTC (rev 203087)
@@ -0,0 +1,60 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad assertion!")
+}
+
+function test(f, n = 4) {
+    for (let i = 0; i < n; i++)
+        f();
+}
+
+test(function() {
+    // This should not crash.
+
+    // FIXME: this might need to be updated as we make our splice implementation
+    // more ES6 compliant: https://bugs.webkit.org/show_bug.cgi?id=159645
+    let x = [1,2,3,4,5];
+    x.constructor = Uint8Array;
+    delete x[2];
+    assert(!(2 in x));
+    let removed = x.splice(1,3);
+    assert(removed instanceof Uint8Array);
+    assert(removed.length === 3);
+    assert(removed[0] === 2);
+    assert(removed[1] === 0);
+    assert(removed[2] === 4);
+
+    assert(x instanceof Array);
+    assert(x.length === 2);
+    assert(x[0] === 1);
+    assert(x[1] === 5);
+});
+
+test(function() {
+    let x = [1,2,3,4,5];
+    x.constructor = Uint8Array;
+    delete x[2];
+    assert(!(2 in x));
+    Object.defineProperty(Uint8Array, Symbol.species, {value: null});
+    assert(Uint8Array[Symbol.species] === null);
+    x = new Proxy(x, {
+        get(target, property, receiver) {
+            if (parseInt(property, 10))
+                assert(property !== "2");
+            return Reflect.get(target, property, receiver);
+        }
+    });
+
+    let removed = x.splice(1,3);
+    assert(removed instanceof Array); // We shouldn't make a TypedArray here because Symbol.species is null.
+    assert(removed.length === 3);
+    assert(removed[0] === 2);
+    assert(removed[1] === undefined);
+    assert(!(1 in removed));
+    assert(removed[2] === 4);
+
+    assert(x instanceof Array);
+    assert(x.length === 2);
+    assert(x[0] === 1);
+    assert(x[1] === 5);
+});
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to