From f6c6047e49f1517778f5565681fb64750b14bf60 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 27 Jan 2021 07:50:46 +0100 Subject: LibJS: Add overflow checks when creating TypedArray from ArrayBuffer Thanks to Iliad for finding this! :^) --- Userland/Libraries/LibJS/Runtime/TypedArray.cpp | 30 +++++++++++++++++----- .../typed-array-from-ArrayBuffer-bad-offset.js | 5 ++++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js (limited to 'Userland/Libraries/LibJS') diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index 13ba159848..60783154ce 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -54,7 +54,7 @@ static void initialize_typed_array_from_array_buffer(GlobalObject& global_object } // FIXME: 8. If IsDetachedBuffer(buffer) is true, throw a TypeError exception. auto buffer_byte_length = array_buffer.byte_length(); - size_t new_byte_length; + Checked new_byte_length; if (length.is_undefined()) { if (buffer_byte_length % element_size != 0) { vm.throw_exception(global_object, ErrorType::TypedArrayInvalidBufferLength, typed_array.class_name(), element_size, buffer_byte_length); @@ -64,18 +64,34 @@ static void initialize_typed_array_from_array_buffer(GlobalObject& global_object vm.throw_exception(global_object, ErrorType::TypedArrayOutOfRangeByteOffset, offset, buffer_byte_length); return; } - new_byte_length = buffer_byte_length - offset; + new_byte_length = buffer_byte_length; + new_byte_length -= offset; } else { - new_byte_length = new_length * element_size; - if (offset + new_byte_length > buffer_byte_length) { - vm.throw_exception(global_object, ErrorType::TypedArrayOutOfRangeByteOffsetOrLength, offset, offset + new_byte_length, buffer_byte_length); + new_byte_length = new_length; + new_byte_length *= element_size; + + Checked new_byte_end = new_byte_length; + new_byte_end += offset; + + if (new_byte_end.has_overflow()) { + vm.throw_exception(global_object, ErrorType::InvalidLength, "typed array"); + return; + } + + if (new_byte_end.value() > buffer_byte_length) { + vm.throw_exception(global_object, ErrorType::TypedArrayOutOfRangeByteOffsetOrLength, offset, new_byte_end.value(), buffer_byte_length); return; } } + if (new_byte_length.has_overflow()) { + vm.throw_exception(global_object, ErrorType::InvalidLength, "typed array"); + return; + } + typed_array.set_viewed_array_buffer(&array_buffer); - typed_array.set_byte_length(new_byte_length); + typed_array.set_byte_length(new_byte_length.value()); typed_array.set_byte_offset(offset); - typed_array.set_array_length(new_byte_length / element_size); + typed_array.set_array_length(new_byte_length.value() / element_size); } void TypedArrayBase::visit_edges(Visitor& visitor) diff --git a/Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js new file mode 100644 index 0000000000..34c8d5d917 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js @@ -0,0 +1,5 @@ +test("construct Uint32Array with zero-length ArrayBuffer and overflowing offset", () => { + expect(() => new Uint32Array(new ArrayBuffer(0), 4, 1024 * 1024 * 1024 - 1)).toThrow( + RangeError + ); +}); -- cgit v1.2.3