
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.
110 lines
5.8 KiB
C++
110 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2022, Daniel Ehrenberg <dan@littledan.dev>
|
|
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
|
* Copyright (c) 2024, Kenneth Myhra <kennethmyhra@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Result.h>
|
|
#include <AK/Types.h>
|
|
#include <AK/Vector.h>
|
|
#include <LibIPC/Forward.h>
|
|
#include <LibJS/Forward.h>
|
|
#include <LibWeb/WebIDL/ExceptionOr.h>
|
|
|
|
// Structured serialize is an entirely different format from IPC because:
|
|
// - It contains representation of type information
|
|
// - It may contain circularities
|
|
// - It is restricted to JS values
|
|
|
|
namespace Web::HTML {
|
|
|
|
using SerializationRecord = Vector<u32>;
|
|
using SerializationMemory = HashMap<JS::Handle<JS::Value>, u32>;
|
|
using DeserializationMemory = JS::MarkedVector<JS::Value>;
|
|
|
|
struct TransferDataHolder {
|
|
Vector<u8> data;
|
|
Vector<IPC::File> fds;
|
|
};
|
|
|
|
struct SerializedTransferRecord {
|
|
SerializationRecord serialized;
|
|
Vector<TransferDataHolder> transfer_data_holders;
|
|
};
|
|
|
|
struct DeserializedTransferRecord {
|
|
JS::Value deserialized;
|
|
Vector<JS::Handle<JS::Object>> transferred_values;
|
|
};
|
|
|
|
enum class TransferType : u8 {
|
|
MessagePort,
|
|
};
|
|
|
|
WebIDL::ExceptionOr<SerializationRecord> structured_serialize(JS::VM& vm, JS::Value);
|
|
WebIDL::ExceptionOr<SerializationRecord> structured_serialize_for_storage(JS::VM& vm, JS::Value);
|
|
WebIDL::ExceptionOr<SerializationRecord> structured_serialize_internal(JS::VM& vm, JS::Value, bool for_storage, SerializationMemory&);
|
|
|
|
WebIDL::ExceptionOr<JS::Value> structured_deserialize(JS::VM& vm, SerializationRecord const& serialized, JS::Realm& target_realm, Optional<DeserializationMemory>);
|
|
|
|
void serialize_boolean_primitive(SerializationRecord& serialized, JS::Value& value);
|
|
void serialize_number_primitive(SerializationRecord& serialized, JS::Value& value);
|
|
WebIDL::ExceptionOr<void> serialize_big_int_primitive(JS::VM& vm, SerializationRecord& serialized, JS::Value& value);
|
|
WebIDL::ExceptionOr<void> serialize_string_primitive(JS::VM& vm, SerializationRecord& serialized, JS::Value& value);
|
|
void serialize_boolean_object(SerializationRecord& serialized, JS::Value& value);
|
|
void serialize_number_object(SerializationRecord& serialized, JS::Value& value);
|
|
WebIDL::ExceptionOr<void> serialize_big_int_object(JS::VM& vm, SerializationRecord& serialized, JS::Value& value);
|
|
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);
|
|
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, String const& string);
|
|
WebIDL::ExceptionOr<void> serialize_string(JS::VM& vm, Vector<u32>& vector, JS::PrimitiveString const& primitive_string);
|
|
WebIDL::ExceptionOr<void> serialize_array_buffer(JS::VM& vm, Vector<u32>& vector, JS::ArrayBuffer const& array_buffer, bool for_storage);
|
|
template<OneOf<JS::TypedArrayBase, JS::DataView> ViewType>
|
|
WebIDL::ExceptionOr<void> serialize_viewed_array_buffer(JS::VM& vm, Vector<u32>& vector, ViewType const& view, bool for_storage, SerializationMemory& memory);
|
|
|
|
bool deserialize_boolean_primitive(ReadonlySpan<u32> const& serialized, size_t& position);
|
|
double deserialize_number_primitive(ReadonlySpan<u32> const& serialized, size_t& position);
|
|
JS::NonnullGCPtr<JS::BooleanObject> deserialize_boolean_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
|
|
JS::NonnullGCPtr<JS::NumberObject> deserialize_number_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
|
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::BigIntObject>> deserialize_big_int_object(JS::Realm& realm, ReadonlySpan<u32> const& serialized, size_t& position);
|
|
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);
|
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::PrimitiveString>> deserialize_string_primitive(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position);
|
|
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::BigInt>> deserialize_big_int_primitive(JS::VM& vm, ReadonlySpan<u32> vector, size_t& position);
|
|
|
|
WebIDL::ExceptionOr<SerializedTransferRecord> structured_serialize_with_transfer(JS::VM& vm, JS::Value value, Vector<JS::Handle<JS::Object>> const& transfer_list);
|
|
WebIDL::ExceptionOr<DeserializedTransferRecord> structured_deserialize_with_transfer(JS::VM& vm, SerializedTransferRecord&);
|
|
|
|
}
|
|
|
|
namespace IPC {
|
|
|
|
template<>
|
|
ErrorOr<void> encode(Encoder&, ::Web::HTML::SerializedTransferRecord const&);
|
|
|
|
template<>
|
|
ErrorOr<void> encode(Encoder&, ::Web::HTML::TransferDataHolder const&);
|
|
|
|
template<>
|
|
ErrorOr<::Web::HTML::SerializedTransferRecord> decode(Decoder&);
|
|
|
|
template<>
|
|
ErrorOr<::Web::HTML::TransferDataHolder> decode(Decoder&);
|
|
|
|
}
|