diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp index 843eefb428..942881df6a 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBuffer.cpp @@ -50,6 +50,23 @@ void ArrayBuffer::visit_edges(Cell::Visitor& visitor) visitor.visit(m_detach_key); } +// 6.2.9.1 CreateByteDataBlock ( size ), https://tc39.es/ecma262/#sec-createbytedatablock +static ThrowCompletionOr create_byte_data_block(VM& vm, size_t size) +{ + // 1. If size > 2^53 - 1, throw a RangeError exception. + if (size > MAX_ARRAY_LIKE_INDEX) + return vm.throw_completion(ErrorType::InvalidLength, "array buffer"); + + // 2. Let db be a new Data Block value consisting of size bytes. If it is impossible to create such a Data Block, throw a RangeError exception. + // 3. Set all of the bytes of db to 0. + auto data_block = ByteBuffer::create_zeroed(size); + if (data_block.is_error()) + return vm.throw_completion(ErrorType::NotEnoughMemoryToAllocate, size); + + // 4. Return db. + return data_block.release_value(); +} + // 25.1.2.1 AllocateArrayBuffer ( constructor, byteLength ), https://tc39.es/ecma262/#sec-allocatearraybuffer ThrowCompletionOr allocate_array_buffer(VM& vm, FunctionObject& constructor, size_t byte_length) { @@ -57,12 +74,10 @@ ThrowCompletionOr allocate_array_buffer(VM& vm, FunctionObject& co auto obj = TRY(ordinary_create_from_constructor(vm, constructor, &Intrinsics::array_buffer_prototype, nullptr)); // 2. Let block be ? CreateByteDataBlock(byteLength). - auto block = ByteBuffer::create_zeroed(byte_length); - if (block.is_error()) - return vm.throw_completion(ErrorType::NotEnoughMemoryToAllocate, byte_length); + auto block = TRY(create_byte_data_block(vm, byte_length)); // 3. Set obj.[[ArrayBufferData]] to block. - obj->set_buffer(block.release_value()); + obj->set_buffer(move(block)); // 4. Set obj.[[ArrayBufferByteLength]] to byteLength. diff --git a/Userland/Libraries/LibJS/Tests/builtins/ArrayBuffer/ArrayBuffer.js b/Userland/Libraries/LibJS/Tests/builtins/ArrayBuffer/ArrayBuffer.js index 8fb05a250c..a09d591680 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/ArrayBuffer/ArrayBuffer.js +++ b/Userland/Libraries/LibJS/Tests/builtins/ArrayBuffer/ArrayBuffer.js @@ -11,3 +11,9 @@ test("ArrayBuffer constructor must be invoked with 'new'", () => { ArrayBuffer(); }).toThrowWithMessage(TypeError, "ArrayBuffer constructor must be called with 'new'"); }); + +test("ArrayBuffer size limit", () => { + expect(() => { + new ArrayBuffer(2 ** 53); + }).toThrowWithMessage(RangeError, "Invalid array buffer length"); +});