summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-27 07:50:46 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-27 07:57:07 +0100
commitf6c6047e49f1517778f5565681fb64750b14bf60 (patch)
treed5328a9bb90340c0fc0dcf1c54f1f6ed7efbe3b0 /Userland/Libraries/LibJS
parentc899ace3ad1efbf1bc8f8ee2ebb1e35903d7224b (diff)
downloadserenity-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.cpp30
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/TypedArray/typed-array-from-ArrayBuffer-bad-offset.js5
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
+ );
+});