Title: [273750] trunk
Revision
273750
Author
[email protected]
Date
2021-03-02 12:00:31 -0800 (Tue, 02 Mar 2021)

Log Message

TypedArray's [[DefineOwnProperty]] should throw in case of failure
https://bugs.webkit.org/show_bug.cgi?id=220492

Reviewed by Darin Adler.

JSTests:

* stress/array-species-config-array-constructor.js:
* stress/put-direct-index-broken-2.js:
Update assertions, which are most certainly incorrect, partly aligning JSC with V8.

* stress/typedarray-access-monomorphic-neutered.js:
* stress/typedarray-access-neutered.js:
* stress/typedarray-defineOwnProperty-error.js: Added.
* test262/expectations.yaml:
Incorrect tests are being updated at https://github.com/tc39/test262/pull/2958.

Source/_javascript_Core:

While web reality [1] requires failures of the most TypeArray internal methods to be
silent, [[DefineOwnProperty]] can fail loudly if called via Object.defineProperty.

With this patch, TypeError is thrown for detached buffer, out-of-bounds index, and
non-index canonical numeric string key. Aligns JSC with the spec [2], V8, and SM.

[1]: https://github.com/tc39/ecma262/pull/2164
[2]: https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-defineownproperty-p-desc (step 3.b)

* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (273749 => 273750)


--- trunk/JSTests/ChangeLog	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/ChangeLog	2021-03-02 20:00:31 UTC (rev 273750)
@@ -1,3 +1,20 @@
+2021-03-02  Alexey Shvayka  <[email protected]>
+
+        TypedArray's [[DefineOwnProperty]] should throw in case of failure
+        https://bugs.webkit.org/show_bug.cgi?id=220492
+
+        Reviewed by Darin Adler.
+
+        * stress/array-species-config-array-constructor.js:
+        * stress/put-direct-index-broken-2.js:
+        Update assertions, which are most certainly incorrect, partly aligning JSC with V8.
+
+        * stress/typedarray-access-monomorphic-neutered.js:
+        * stress/typedarray-access-neutered.js:
+        * stress/typedarray-defineOwnProperty-error.js: Added.
+        * test262/expectations.yaml:
+        Incorrect tests are being updated at https://github.com/tc39/test262/pull/2958.
+
 2021-03-01  Yusuke Suzuki  <[email protected]>
 
         REGRESSION: Object.defineProperties triggering a setter

Modified: trunk/JSTests/stress/array-species-config-array-constructor.js (273749 => 273750)


--- trunk/JSTests/stress/array-species-config-array-constructor.js	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/stress/array-species-config-array-constructor.js	2021-03-02 20:00:31 UTC (rev 273750)
@@ -31,7 +31,9 @@
 }
 
 function test() {
-    foo.concat([1]);
+    shouldThrow(() => {
+        foo.concat([1]);
+    }, "TypeError: Attempting to store out-of-bounds property on a typed array at index: 0");
     foo = [1,2,3,4];
     foo.slice(0);
     foo = [1,2,3,4];

Modified: trunk/JSTests/stress/put-direct-index-broken-2.js (273749 => 273750)


--- trunk/JSTests/stress/put-direct-index-broken-2.js	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/stress/put-direct-index-broken-2.js	2021-03-02 20:00:31 UTC (rev 273750)
@@ -56,7 +56,7 @@
     } catch(e) {
         err = e;
     }
-    assert(!err);
+    assert(err.toString() == "TypeError: Attempting to store out-of-bounds property on a typed array at index: 0");
 });
 
 test(function() {

Modified: trunk/JSTests/stress/typedarray-access-monomorphic-neutered.js (273749 => 273750)


--- trunk/JSTests/stress/typedarray-access-monomorphic-neutered.js	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/stress/typedarray-access-monomorphic-neutered.js	2021-03-02 20:00:31 UTC (rev 273750)
@@ -20,7 +20,6 @@
     testNoException("Object.getOwnPropertyDescriptor(array, 0)", array);
     testNoException("array[0] = 1", array);
     testNoException("array[i] = 1", array);
-    testNoException("Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true })", array);
 }
 
 function testFTLNoException(thunk, array, failArray) {
@@ -40,5 +39,4 @@
     testFTLNoException("Object.getOwnPropertyDescriptor(array, 0)", array, failArray);
     testFTLNoException("array[0] = 1", array, failArray);
     testFTLNoException("array[i] = 1", array, failArray);
-    testFTLNoException("Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true })", array, failArray);
 }

Modified: trunk/JSTests/stress/typedarray-access-neutered.js (273749 => 273750)


--- trunk/JSTests/stress/typedarray-access-neutered.js	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/stress/typedarray-access-neutered.js	2021-03-02 20:00:31 UTC (rev 273750)
@@ -16,5 +16,4 @@
     testNoException((array) => delete array[0], i);
     testNoException((array) => Object.getOwnPropertyDescriptor(array, 0), i);
     testNoException((array) => array[0] = 1, i);
-    testNoException((array) => Object.defineProperty(array, 0, { value: 1, writable: true, configurable: true, enumerable: true }), i)
 }

Added: trunk/JSTests/stress/typedarray-defineOwnProperty-error.js (0 => 273750)


--- trunk/JSTests/stress/typedarray-defineOwnProperty-error.js	                        (rev 0)
+++ trunk/JSTests/stress/typedarray-defineOwnProperty-error.js	2021-03-02 20:00:31 UTC (rev 273750)
@@ -0,0 +1,78 @@
+function shouldThrow(func, expectedError) {
+    var errorThrown = false;
+    try {
+        func();
+    } catch (error) {
+        errorThrown = true;
+        if (error.toString() !== expectedError)
+            throw new Error(`Bad error: ${error}!`);
+    }
+    if (!errorThrown)
+        throw new Error("Not thrown!");
+}
+
+function testException(func, expectedError) {
+    for (const TA of [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array]) {
+        for (let i = 0; i < 1e4; i++)
+            shouldThrow(() => func(TA), expectedError);
+    }
+}
+
+testException(TA => {
+    let ta = new TA(4);
+    transferArrayBuffer(ta.buffer);
+    Object.defineProperty(ta, "0", {value: 1});
+}, "TypeError: Underlying ArrayBuffer has been detached from the view");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "10", {value: 1});
+}, "TypeError: Attempting to store out-of-bounds property on a typed array at index: 10");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "1", {get() {}});
+}, "TypeError: Attempting to store accessor property on a typed array at index: 1");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "1", {set(_v) {}});
+}, "TypeError: Attempting to store accessor property on a typed array at index: 1");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "2", {configurable: false});
+}, "TypeError: Attempting to store non-configurable property on a typed array at index: 2");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "3", {enumerable: false});
+}, "TypeError: Attempting to store non-enumerable property on a typed array at index: 3");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "0", {writable: false});
+}, "TypeError: Attempting to store non-writable property on a typed array at index: 0");
+
+const myError = new Error("foo");
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "1", {
+        value: { valueOf() { throw myError; } },
+    });
+}, myError.toString());
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "-1", {value: 1});
+}, "TypeError: Attempting to store canonical numeric string property on a typed array");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "0.5", {value: 1});
+}, "TypeError: Attempting to store canonical numeric string property on a typed array");
+
+testException(TA => {
+    let ta = new TA(4);
+    Object.defineProperty(ta, "NaN", {value: 1});
+}, "TypeError: Attempting to store canonical numeric string property on a typed array");

Modified: trunk/JSTests/test262/expectations.yaml (273749 => 273750)


--- trunk/JSTests/test262/expectations.yaml	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/JSTests/test262/expectations.yaml	2021-03-02 20:00:31 UTC (rev 273750)
@@ -826,6 +826,12 @@
 test/built-ins/RegExp/quantifier-integer-limit.js:
   default: 'SyntaxError: Invalid regular _expression_: number too large in {} quantifier'
   strict mode: 'SyntaxError: Invalid regular _expression_: number too large in {} quantifier'
+test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/tonumber-value-detached-buffer.js:
+  default: 'Test262Error: Reflect.defineProperty(ta, 0, {value: {valueOf() {$DETACHBUFFER(ta.buffer); return 42n;}}}) must return false Expected SameValue(«true», «false») to be true (Testing with BigInt64Array.)'
+  strict mode: 'Test262Error: Reflect.defineProperty(ta, 0, {value: {valueOf() {$DETACHBUFFER(ta.buffer); return 42n;}}}) must return false Expected SameValue(«true», «false») to be true (Testing with BigInt64Array.)'
+test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/tonumber-value-detached-buffer.js:
+  default: 'Test262Error: Reflect.defineProperty(ta, 0, {value: {valueOf() {$DETACHBUFFER(ta.buffer); return 42;}}} ) must return false Expected SameValue(«true», «false») to be true (Testing with Float64Array.)'
+  strict mode: 'Test262Error: Reflect.defineProperty(ta, 0, {value: {valueOf() {$DETACHBUFFER(ta.buffer); return 42;}}} ) must return false Expected SameValue(«true», «false») to be true (Testing with Float64Array.)'
 test/intl402/DateTimeFormat/prototype/formatRange/en-US.js:
   default: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true'
   strict mode: 'Test262Error: Expected SameValue(«1/3/2019 – 1/5/2019», «1/3/2019 – 1/5/2019») to be true'

Modified: trunk/Source/_javascript_Core/ChangeLog (273749 => 273750)


--- trunk/Source/_javascript_Core/ChangeLog	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-03-02 20:00:31 UTC (rev 273750)
@@ -1,3 +1,22 @@
+2021-03-02  Alexey Shvayka  <[email protected]>
+
+        TypedArray's [[DefineOwnProperty]] should throw in case of failure
+        https://bugs.webkit.org/show_bug.cgi?id=220492
+
+        Reviewed by Darin Adler.
+
+        While web reality [1] requires failures of the most TypeArray internal methods to be
+        silent, [[DefineOwnProperty]] can fail loudly if called via Object.defineProperty.
+
+        With this patch, TypeError is thrown for detached buffer, out-of-bounds index, and
+        non-index canonical numeric string key. Aligns JSC with the spec [2], V8, and SM.
+
+        [1]: https://github.com/tc39/ecma262/pull/2164
+        [2]: https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-defineownproperty-p-desc (step 3.b)
+
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):
+
 2021-03-01  Keith Miller  <[email protected]>
 
         Reduce promise reaction memory usage when there are multiple reactions

Modified: trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h (273749 => 273750)


--- trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2021-03-02 19:51:34 UTC (rev 273749)
+++ trunk/Source/_javascript_Core/runtime/JSGenericTypedArrayViewInlines.h	2021-03-02 20:00:31 UTC (rev 273750)
@@ -403,9 +403,12 @@
             return false;
         };
 
-        if (index.value() >= thisObject->m_length)
-            return false;
+        if (thisObject->isDetached())
+            return typeError(globalObject, scope, shouldThrow, typedArrayBufferHasBeenDetachedErrorMessage);
 
+        if (!thisObject->inBounds(index.value()))
+            return throwTypeErrorIfNeeded("Attempting to store out-of-bounds property on a typed array at index: ");
+
         if (descriptor.isAccessorDescriptor())
             return throwTypeErrorIfNeeded("Attempting to store accessor property on a typed array at index: ");
 
@@ -418,14 +421,15 @@
         if (descriptor.writablePresent() && !descriptor.writable())
             return throwTypeErrorIfNeeded("Attempting to store non-writable property on a typed array at index: ");
 
+        scope.release();
         if (descriptor.value())
-            RELEASE_AND_RETURN(scope, thisObject->setIndex(globalObject, index.value(), descriptor.value()));
+            thisObject->setIndex(globalObject, index.value(), descriptor.value());
 
         return true;
     }
 
     if (isCanonicalNumericIndexString(propertyName))
-        return false;
+        return typeError(globalObject, scope, shouldThrow, "Attempting to store canonical numeric string property on a typed array"_s);
 
     RELEASE_AND_RETURN(scope, Base::defineOwnProperty(thisObject, globalObject, propertyName, descriptor, shouldThrow));
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to