Skip to content

Commit

Permalink
RAB: Integrate staging tests for the .subarray method (tc39#4177)
Browse files Browse the repository at this point in the history
* Import relevant files from tc39#3888

* Adds resizableArrayBufferUtils.js to includes and removes its content from each test

* renamed tests to indicate the end argument is tested too

* Adds more tests for the 'end' argument of .subarray
  • Loading branch information
ioannad authored Aug 15, 2024
1 parent cb4a6c8 commit 224c5c3
Show file tree
Hide file tree
Showing 3 changed files with 470 additions and 0 deletions.
106 changes: 106 additions & 0 deletions test/built-ins/TypedArray/prototype/subarray/coerced-begin-end-grow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.subarray
description: >
TypedArray.p.subarray behaves correctly on TypedArrays backed by resizable
buffers that are grown by argument coercion.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/

// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [0, 2, 4, 6, ...] << lengthTracking

// Growing a fixed length TA back in bounds.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// Make `fixedLength` OOB.
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
const evil = {
valueOf: () => {
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
// The length computation is done before parameter conversion. At that
// point, the length is 0, since the TA is OOB.
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), []);
}

// As above but with the second parameter conversion growing the buffer.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
// Make `fixedLength` OOB.
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
const evil = {
valueOf: () => {
rab.resize(4 * ctor.BYTES_PER_ELEMENT);
return 1;
}
};
// The length computation is done before parameter conversion. At that
// point, the length is 0, since the TA is OOB.
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), []);
}


// Growing + fixed-length TA. Growing won't affect anything.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(evil)), [
0,
2,
4,
6
]);
}

// As above but with the second parameter conversion growing the buffer.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 4;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), [
0,
2,
4,
6
]);
}

// Growing + length-tracking TA. The length computation is done with the
// original length.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab, 0);
const evil = {
valueOf: () => {
rab.resize(6 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(
ToNumbers(lengthTracking.subarray(evil, lengthTracking.length)), [
0,
2,
4,
6
]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Copyright 2023 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.

/*---
esid: sec-%typedarray%.prototype.subarray
description: >
TypedArray.p.subarray behaves correctly on TypedArrays backed by resizable
buffers that are shrunk by argument coercion.
includes: [compareArray.js, resizableArrayBufferUtils.js]
features: [resizable-arraybuffer]
---*/

// Orig. array: [0, 2, 4, 6]
// [0, 2, 4, 6] << fixedLength
// [0, 2, 4, 6, ...] << lengthTracking


// Fixed-length TA + first parameter conversion shrinks. The old length is
// used in the length computation, and the subarray construction fails.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.throws(RangeError, () => {
fixedLength.subarray(evil);
});
}

// Like the previous test, but now we construct a smaller subarray and it
// succeeds.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), [0]);
}

// As above but with the second parameter conversion shrinking the buffer.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 1;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(0,evil)), [0]);
}

// Fixed-length TA + second parameter conversion shrinks. The old length is
// used in the length computation, and the subarray construction fails.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 3;
}
};
assert.throws(RangeError, () => {
fixedLength.subarray(0, evil);
});
}

// Like the previous test, but now we construct a smaller subarray and it
// succeeds.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 1;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(0, evil)), [0]);
}

// Shrinking + fixed-length TA, subarray construction succeeds even though the
// TA goes OOB.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(evil, 1)), [0]);
}

// As above but with the second parameter conversion shrinking the buffer.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const fixedLength = new ctor(rab, 0, 4);
const evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 1;
}
};
assert.compareArray(ToNumbers(fixedLength.subarray(0,evil)), [0]);
}

// Length-tracking TA + first parameter conversion shrinks. The old length is
// used in the length computation, and the subarray construction fails.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.throws(RangeError, () => {
lengthTracking.subarray(evil, lengthTracking.length);
});
}

// Like the previous test, but now we construct a smaller subarray and it
// succeeds.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.compareArray(ToNumbers(lengthTracking.subarray(evil, 1)), [0]);
}

// As above but with the second parameter conversion shrinking the buffer.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 1;
}
};
assert.compareArray(ToNumbers(lengthTracking.subarray(0,evil)), [0]);
}

// Length-tracking TA + first parameter conversion shrinks. The second
// parameter is negative -> the relative index is not recomputed, and the
// subarray construction fails.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 0;
}
};
assert.throws(RangeError, () => {
lengthTracking.subarray(evil, -1);
});
}

// Length-tracking TA + second parameter conversion shrinks. The second
// parameter is too large -> the subarray construction fails.
for (let ctor of ctors) {
const rab = CreateRabForTest(ctor);
const lengthTracking = new ctor(rab);
let evil = {
valueOf: () => {
rab.resize(2 * ctor.BYTES_PER_ELEMENT);
return 3;
}
};
assert.throws(RangeError, () => {
lengthTracking.subarray(0, evil);
});
}
Loading

0 comments on commit 224c5c3

Please sign in to comment.