LibJS: Avoid internal assertion accessing detached TA internal slots

This defers accessing TA internal slots until we know we have a valid,
attached TA. Our implementation has assertions that guard against this.
This commit is contained in:
Timothy Flynn 2024-12-13 09:24:12 -05:00 committed by Tim Flynn
parent 5d85f3a5c8
commit 962441b3cf
Notes: github-actions[bot] 2024-12-13 15:10:36 +00:00
2 changed files with 27 additions and 6 deletions

View file

@ -290,12 +290,6 @@ static ThrowCompletionOr<Value> atomic_compare_exchange_impl(VM& vm, TypedArrayB
// 1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index).
auto byte_index_in_buffer = TRY(validate_atomic_access_on_integer_typed_array(vm, typed_array, index));
// 2. Let buffer be typedArray.[[ViewedArrayBuffer]].
auto* buffer = typed_array.viewed_array_buffer();
// 3. Let block be buffer.[[ArrayBufferData]].
auto& block = buffer->buffer();
Value expected;
Value replacement;
@ -319,6 +313,15 @@ static ThrowCompletionOr<Value> atomic_compare_exchange_impl(VM& vm, TypedArrayB
// 6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
TRY(revalidate_atomic_access(vm, typed_array, byte_index_in_buffer));
// NOTE: We defer steps 2 and 3 to ensure we have revalidated the TA before accessing these internal slots.
// In our implementation, accessing [[ArrayBufferData]] on a detached buffer will fail assertions.
// 2. Let buffer be typedArray.[[ViewedArrayBuffer]].
auto* buffer = typed_array.viewed_array_buffer();
// 3. Let block be buffer.[[ArrayBufferData]].
auto& block = buffer->buffer();
// 7. Let elementType be TypedArrayElementType(typedArray).
// 8. Let elementSize be TypedArrayElementSize(typedArray).

View file

@ -21,6 +21,24 @@ test("error cases", () => {
const array = new Int32Array(4);
Atomics.compareExchange(array, 100, 0, 0);
}).toThrow(RangeError);
expect(() => {
const array = new Int32Array(4);
function detachArrayWhileAccessingIndex(array) {
return {
valueOf() {
detachArrayBuffer(array.buffer);
return 0;
},
};
}
Atomics.compareExchange(array, detachArrayWhileAccessingIndex(array), 0, 0);
}).toThrowWithMessage(
TypeError,
"TypedArray contains a property which references a value at an index not contained within its buffer's bounds"
);
});
test("basic functionality (non-BigInt)", () => {