Skip to content

Commit

Permalink
LibWeb: Add convenience methods {,de}serialize_{u,i}64()
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kennethmyhra authored and ADKaster committed Mar 3, 2024
1 parent d269ac6 commit 4751ab9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 11 deletions.
7 changes: 2 additions & 5 deletions Userland/Libraries/LibWeb/FileAPI/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ WebIDL::ExceptionOr<void> 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<u32*>(&m_last_modified), 2);
HTML::serialize_i64(record, m_last_modified);

return {};
}
Expand All @@ -128,10 +128,7 @@ WebIDL::ExceptionOr<void> File::deserialization_steps(ReadonlySpan<u32> 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<i64*>(&bits);
m_last_modified = HTML::deserialize_i64(record, position);

return {};
}
Expand Down
38 changes: 32 additions & 6 deletions Userland/Libraries/LibWeb/HTML/StructuredSerialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,21 @@ WebIDL::ExceptionOr<void> serialize_reg_exp_object(JS::VM& vm, SerializationReco
return {};
}

void serialize_u64(SerializationRecord& serialized, u64 value)
{
serialized.append(bit_cast<u32*>(&value), 2);
}

void serialize_i64(SerializationRecord& serialized, i64 value)
{
serialized.append(bit_cast<u32*>(&value), 2);
}

WebIDL::ExceptionOr<void> serialize_bytes(JS::VM& vm, Vector<u32>& 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<u32*>(&size), 2));
serialize_u64(vector, size);
// Append the bytes of the buffer to the serialized structure.
u64 byte_position = 0;
while (byte_position < size) {
Expand Down Expand Up @@ -1044,13 +1054,29 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::RegExpObject>> deserialize_reg_exp_obje
return TRY(JS::regexp_create(realm.vm(), move(pattern), move(flags)));
}

u64 deserialize_u64(ReadonlySpan<u32> const& serialized, size_t& position)
{
VERIFY(position + 2 <= serialized.size());
u32 const bits[2] {
serialized[position++],
serialized[position++],
};
return *bit_cast<u64*>(&bits);
}

i64 deserialize_i64(ReadonlySpan<u32> const& serialized, size_t& position)
{
VERIFY(position + 2 <= serialized.size());
u32 const bits[2] {
serialized[position++],
serialized[position++],
};
return *bit_cast<i64*>(&bits);
}

WebIDL::ExceptionOr<ByteBuffer> deserialize_bytes(JS::VM& vm, ReadonlySpan<u32> 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<u64*>(&size_bits);
u64 const size = deserialize_u64(vector, position);

auto bytes = TRY_OR_THROW_OOM(vm, ByteBuffer::create_uninitialized(size));
u64 byte_position = 0;
Expand Down
4 changes: 4 additions & 0 deletions Userland/Libraries/LibWeb/HTML/StructuredSerialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ WebIDL::ExceptionOr<void> serialize_big_int_object(JS::VM& vm, SerializationReco
WebIDL::ExceptionOr<void> serialize_string_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value);
void serialize_date_object(SerializationRecord& serialized, JS::Value& value);
WebIDL::ExceptionOr<void> 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<void> serialize_bytes(JS::VM& vm, Vector<u32>& vector, ReadonlyBytes bytes);
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, DeprecatedFlyString const& string);
Expand All @@ -78,6 +80,8 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::BigIntObject>> deserialize_big_int_obje
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::StringObject>> deserialize_string_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
JS::NonnullGCPtr<JS::Date> deserialize_date_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::RegExpObject>> deserialize_reg_exp_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
u64 deserialize_u64(ReadonlySpan<u32> const& serialized, size_t& position);
i64 deserialize_i64(ReadonlySpan<u32> const& serialized, size_t& position);

WebIDL::ExceptionOr<ByteBuffer> deserialize_bytes(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position);
WebIDL::ExceptionOr<String> deserialize_string(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position);
Expand Down

0 comments on commit 4751ab9

Please sign in to comment.