diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-27 07:50:46 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-27 07:57:07 +0100 |
commit | f6c6047e49f1517778f5565681fb64750b14bf60 (patch) | |
tree | d5328a9bb90340c0fc0dcf1c54f1f6ed7efbe3b0 /Userland/Libraries/LibJS | |
parent | c899ace3ad1efbf1bc8f8ee2ebb1e35903d7224b (diff) | |
download | serenity-f6c6047e49f1517778f5565681fb64750b14bf60.zip |
LibJS: Add overflow checks when creating TypedArray from ArrayBuffer
Thanks to Iliad for finding this! :^)
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/TypedArray.cpp | 30 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js | 5 |
2 files changed, 28 insertions, 7 deletions
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<size_t> new_byte_length; if (length.is_undefined()) { if (buffer_byte_length % element_size != 0) { vm.throw_exception<RangeError>(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<RangeError>(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<RangeError>(global_object, ErrorType::TypedArrayOutOfRangeByteOffsetOrLength, offset, offset + new_byte_length, buffer_byte_length); + new_byte_length = new_length; + new_byte_length *= element_size; + + Checked<size_t> new_byte_end = new_byte_length; + new_byte_end += offset; + + if (new_byte_end.has_overflow()) { + vm.throw_exception<RangeError>(global_object, ErrorType::InvalidLength, "typed array"); + return; + } + + if (new_byte_end.value() > buffer_byte_length) { + vm.throw_exception<RangeError>(global_object, ErrorType::TypedArrayOutOfRangeByteOffsetOrLength, offset, new_byte_end.value(), buffer_byte_length); return; } } + if (new_byte_length.has_overflow()) { + vm.throw_exception<RangeError>(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 + ); +}); |