From 4751ab9f0b04a74a99d40330a403ec8034276818 Mon Sep 17 00:00:00 2001 From: Kenneth Myhra Date: Sat, 2 Mar 2024 21:33:07 +0100 Subject: [PATCH] LibWeb: Add convenience methods {,de}serialize_{u,i}64() To avoid differing logic for serializing and deserializing similar types, move the logic into separate helpers. Also, adds security checks like VERIFY to avoid reading past the end of the serialized data. If we try to read past the end of the serialized data, either our program logic is wrong or our serialized data has somehow been corrupted. Therefore, at least currently, it is better to crash by VERIFYing. --- Userland/Libraries/LibWeb/FileAPI/File.cpp | 7 +--- .../LibWeb/HTML/StructuredSerialize.cpp | 38 ++++++++++++++++--- .../LibWeb/HTML/StructuredSerialize.h | 4 ++ 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibWeb/FileAPI/File.cpp b/Userland/Libraries/LibWeb/FileAPI/File.cpp index c468dbb44d..db6e71d1a5 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/File.cpp @@ -106,7 +106,7 @@ WebIDL::ExceptionOr File::serialization_steps(HTML::SerializationRecord& r TRY(HTML::serialize_string(vm, record, m_name)); // 4. Set serialized.[[LastModified]] to the value of value’s lastModified attribute. - record.append(bit_cast(&m_last_modified), 2); + HTML::serialize_i64(record, m_last_modified); return {}; } @@ -128,10 +128,7 @@ WebIDL::ExceptionOr File::deserialization_steps(ReadonlySpan const& r m_name = TRY(HTML::deserialize_string(vm, record, position)); // 4. Initialize the value of value’s lastModified attribute to serialized.[[LastModified]]. - u32 bits[2] = {}; - bits[0] = record[position++]; - bits[1] = record[position++]; - m_last_modified = *bit_cast(&bits); + m_last_modified = HTML::deserialize_i64(record, position); return {}; } diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp index 90439b0792..c0b2d6fc94 100644 --- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp +++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp @@ -507,11 +507,21 @@ WebIDL::ExceptionOr serialize_reg_exp_object(JS::VM& vm, SerializationReco return {}; } +void serialize_u64(SerializationRecord& serialized, u64 value) +{ + serialized.append(bit_cast(&value), 2); +} + +void serialize_i64(SerializationRecord& serialized, i64 value) +{ + serialized.append(bit_cast(&value), 2); +} + WebIDL::ExceptionOr serialize_bytes(JS::VM& vm, Vector& vector, ReadonlyBytes bytes) { // Append size of the buffer to the serialized structure. u64 const size = bytes.size(); - TRY_OR_THROW_OOM(vm, vector.try_append(bit_cast(&size), 2)); + serialize_u64(vector, size); // Append the bytes of the buffer to the serialized structure. u64 byte_position = 0; while (byte_position < size) { @@ -1044,13 +1054,29 @@ WebIDL::ExceptionOr> deserialize_reg_exp_obje return TRY(JS::regexp_create(realm.vm(), move(pattern), move(flags))); } +u64 deserialize_u64(ReadonlySpan const& serialized, size_t& position) +{ + VERIFY(position + 2 <= serialized.size()); + u32 const bits[2] { + serialized[position++], + serialized[position++], + }; + return *bit_cast(&bits); +} + +i64 deserialize_i64(ReadonlySpan const& serialized, size_t& position) +{ + VERIFY(position + 2 <= serialized.size()); + u32 const bits[2] { + serialized[position++], + serialized[position++], + }; + return *bit_cast(&bits); +} + WebIDL::ExceptionOr deserialize_bytes(JS::VM& vm, ReadonlySpan vector, size_t& position) { - VERIFY(position + 2 <= vector.size()); - u32 size_bits[2]; - size_bits[0] = vector[position++]; - size_bits[1] = vector[position++]; - u64 const size = *bit_cast(&size_bits); + u64 const size = deserialize_u64(vector, position); auto bytes = TRY_OR_THROW_OOM(vm, ByteBuffer::create_uninitialized(size)); u64 byte_position = 0; diff --git a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h index 74f549cd6e..014d6978b5 100644 --- a/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h +++ b/Userland/Libraries/LibWeb/HTML/StructuredSerialize.h @@ -61,6 +61,8 @@ WebIDL::ExceptionOr serialize_big_int_object(JS::VM& vm, SerializationReco WebIDL::ExceptionOr serialize_string_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); void serialize_date_object(SerializationRecord& serialized, JS::Value& value); WebIDL::ExceptionOr serialize_reg_exp_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value); +void serialize_u64(SerializationRecord& serialized, u64 value); +void serialize_i64(SerializationRecord& serialized, i64 value); WebIDL::ExceptionOr serialize_bytes(JS::VM& vm, Vector& vector, ReadonlyBytes bytes); WebIDL::ExceptionOr serialize_string(JS::VM& vm, Vector& vector, DeprecatedFlyString const& string); @@ -78,6 +80,8 @@ WebIDL::ExceptionOr> deserialize_big_int_obje WebIDL::ExceptionOr> deserialize_string_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); JS::NonnullGCPtr deserialize_date_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); WebIDL::ExceptionOr> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan const& serialized, size_t& position); +u64 deserialize_u64(ReadonlySpan const& serialized, size_t& position); +i64 deserialize_i64(ReadonlySpan const& serialized, size_t& position); WebIDL::ExceptionOr deserialize_bytes(JS::VM& vm, ReadonlySpan vector, size_t& position); WebIDL::ExceptionOr deserialize_string(JS::VM& vm, ReadonlySpan vector, size_t& position);