From be8e1cbed551b67d0203aac123801f202143abd4 Mon Sep 17 00:00:00 2001 From: Alex Christensen Date: Wed, 19 Apr 2023 08:08:12 -0700 Subject: [PATCH] Verify non-serialized members of serialized types are not accidentally forgotten https://bugs.webkit.org/show_bug.cgi?id=255551 rdar://108161764 Reviewed by Chris Dumez. I introduce the NotSerialized attribute for members that are ... not serialized. Until we have https://wg21.link/P1240 in the language, we can't iterate the members at compile time and make sure we got them all. We already use MembersInCorrectOrder to make sure we got them in the correct order, but we didn't have a check that we got them all until now. This makes a struct that has the same members in the same order and static_asserts that it has the same size as the actual struct. To reduce memory use and make this new sizeof trick work, I made ReportBody::type() a virtual function call instead of using another byte to store the type. * Source/WebCore/Modules/reporting/DeprecationReportBody.cpp: (WebCore::DeprecationReportBody::DeprecationReportBody): * Source/WebCore/Modules/reporting/DeprecationReportBody.h: * Source/WebCore/Modules/reporting/ReportBody.cpp: (WebCore::ReportBody::ReportBody): Deleted. (WebCore::ReportBody::reportBodyType const): Deleted. * Source/WebCore/Modules/reporting/ReportBody.h: * Source/WebCore/Modules/reporting/TestReportBody.cpp: (WebCore::TestReportBody::TestReportBody): * Source/WebCore/Modules/reporting/TestReportBody.h: * Source/WebCore/loader/COEPInheritenceViolationReportBody.cpp: (WebCore::COEPInheritenceViolationReportBody::COEPInheritenceViolationReportBody): * Source/WebCore/loader/COEPInheritenceViolationReportBody.h: * Source/WebCore/loader/CORPViolationReportBody.cpp: (WebCore::CORPViolationReportBody::CORPViolationReportBody): * Source/WebCore/loader/CORPViolationReportBody.h: * Source/WebCore/page/csp/CSPViolationReportBody.cpp: (WebCore::CSPViolationReportBody::CSPViolationReportBody): * Source/WebCore/page/csp/CSPViolationReportBody.h: * Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.serialization.in: * Source/WebKit/Scripts/generate-serializers.py: (SerializedType.__init__): (SerializedType.has_bit_field): (SerializedType): (SerializedType.serialized_members): (check_type_members): (check_type_members.is): (check_type_members.is.is): (encode_type): (decode_type): (construct_type): (generate_impl): (generate_serialized_type_info): * Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp: (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::encode): (IPC::ArgumentCoder::decode): * Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h: * Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp: * Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in: * Source/WebKit/Shared/SessionState.serialization.in: * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: Canonical link: https://commits.webkit.org/263133@main --- .../reporting/DeprecationReportBody.cpp | 3 +- .../Modules/reporting/DeprecationReportBody.h | 2 + .../WebCore/Modules/reporting/ReportBody.cpp | 9 -- Source/WebCore/Modules/reporting/ReportBody.h | 8 +- .../Modules/reporting/TestReportBody.cpp | 3 +- .../Modules/reporting/TestReportBody.h | 2 + .../COEPInheritenceViolationReportBody.cpp | 3 +- .../COEPInheritenceViolationReportBody.h | 2 + .../loader/CORPViolationReportBody.cpp | 3 +- .../WebCore/loader/CORPViolationReportBody.h | 2 + .../page/csp/CSPViolationReportBody.cpp | 6 +- .../WebCore/page/csp/CSPViolationReportBody.h | 2 + ...orkResourceLoadParameters.serialization.in | 6 +- Source/WebKit/Scripts/generate-serializers.py | 83 +++++++++--- .../webkit/tests/GeneratedSerializers.cpp | 118 ++++++++++++++++-- .../webkit/tests/GeneratedSerializers.h | 16 +-- .../webkit/tests/SerializedTypeInfo.cpp | 6 +- .../tests/TestSerializedType.serialization.in | 5 +- .../Shared/SessionState.serialization.in | 4 +- .../WebCoreArgumentCoders.serialization.in | 14 ++- 20 files changed, 225 insertions(+), 72 deletions(-) diff --git a/Source/WebCore/Modules/reporting/DeprecationReportBody.cpp b/Source/WebCore/Modules/reporting/DeprecationReportBody.cpp index 9cc45fbeb423..9ef5830a8884 100644 --- a/Source/WebCore/Modules/reporting/DeprecationReportBody.cpp +++ b/Source/WebCore/Modules/reporting/DeprecationReportBody.cpp @@ -37,8 +37,7 @@ namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(DeprecationReportBody); DeprecationReportBody::DeprecationReportBody(String&& id, WallTime anticipatedRemoval, String&& message, String&& sourceFile, std::optional lineNumber, std::optional columnNumber) - : ReportBody(ViolationReportType::Deprecation) - , m_id(WTFMove(id)) + : m_id(WTFMove(id)) , m_anticipatedRemoval(anticipatedRemoval) , m_message(WTFMove(message)) , m_sourceFile(WTFMove(sourceFile)) diff --git a/Source/WebCore/Modules/reporting/DeprecationReportBody.h b/Source/WebCore/Modules/reporting/DeprecationReportBody.h index 7550639f6674..9af2a0c0fa5e 100644 --- a/Source/WebCore/Modules/reporting/DeprecationReportBody.h +++ b/Source/WebCore/Modules/reporting/DeprecationReportBody.h @@ -53,6 +53,8 @@ class DeprecationReportBody final : public ReportBody { private: DeprecationReportBody(String&& id, WallTime anticipatedRemoval, String&& message, String&& sourceFile, std::optional lineNumber, std::optional columnNumber); + ViolationReportType reportBodyType() const final { return ViolationReportType::Deprecation; } + const String m_id; const WallTime m_anticipatedRemoval; const String m_message; diff --git a/Source/WebCore/Modules/reporting/ReportBody.cpp b/Source/WebCore/Modules/reporting/ReportBody.cpp index 54e289bdda1a..d5d87eb60ec5 100644 --- a/Source/WebCore/Modules/reporting/ReportBody.cpp +++ b/Source/WebCore/Modules/reporting/ReportBody.cpp @@ -33,15 +33,6 @@ namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(ReportBody); -ReportBody::ReportBody(ViolationReportType type) - : m_reportBodyType(type) -{ } - ReportBody::~ReportBody() = default; -ViolationReportType ReportBody::reportBodyType() const -{ - return m_reportBodyType; -} - } // namespace WebCore diff --git a/Source/WebCore/Modules/reporting/ReportBody.h b/Source/WebCore/Modules/reporting/ReportBody.h index e85f3a3d1cba..4488404bca4f 100644 --- a/Source/WebCore/Modules/reporting/ReportBody.h +++ b/Source/WebCore/Modules/reporting/ReportBody.h @@ -38,13 +38,7 @@ class WEBCORE_EXPORT ReportBody : public RefCounted { virtual ~ReportBody(); virtual const String& type() const = 0; - ViolationReportType reportBodyType() const; - -protected: - ReportBody(ViolationReportType); - -private: - ViolationReportType m_reportBodyType; + virtual ViolationReportType reportBodyType() const = 0; }; } // namespace WebCore diff --git a/Source/WebCore/Modules/reporting/TestReportBody.cpp b/Source/WebCore/Modules/reporting/TestReportBody.cpp index 85b80184a30b..e7ae040d2725 100644 --- a/Source/WebCore/Modules/reporting/TestReportBody.cpp +++ b/Source/WebCore/Modules/reporting/TestReportBody.cpp @@ -34,8 +34,7 @@ namespace WebCore { WTF_MAKE_ISO_ALLOCATED_IMPL(TestReportBody); TestReportBody::TestReportBody(String&& message) - : ReportBody(ViolationReportType::Test) - , m_bodyMessage(WTFMove(message)) + : m_bodyMessage(WTFMove(message)) { } diff --git a/Source/WebCore/Modules/reporting/TestReportBody.h b/Source/WebCore/Modules/reporting/TestReportBody.h index e463ac723679..1c656b7c1524 100644 --- a/Source/WebCore/Modules/reporting/TestReportBody.h +++ b/Source/WebCore/Modules/reporting/TestReportBody.h @@ -45,6 +45,8 @@ class TestReportBody final : public ReportBody { private: TestReportBody(String&& message); + ViolationReportType reportBodyType() const final { return ViolationReportType::Test; } + const String m_bodyMessage; }; diff --git a/Source/WebCore/loader/COEPInheritenceViolationReportBody.cpp b/Source/WebCore/loader/COEPInheritenceViolationReportBody.cpp index 5d40c49fe240..2de587fa6b18 100644 --- a/Source/WebCore/loader/COEPInheritenceViolationReportBody.cpp +++ b/Source/WebCore/loader/COEPInheritenceViolationReportBody.cpp @@ -39,8 +39,7 @@ Ref COEPInheritenceViolationReportBody::crea } COEPInheritenceViolationReportBody::COEPInheritenceViolationReportBody(COEPDisposition disposition, const URL& blockedURL, const String& type) - : ReportBody(ViolationReportType::COEPInheritenceViolation) - , m_disposition(disposition) + : m_disposition(disposition) , m_blockedURL(blockedURL) , m_type(type) { diff --git a/Source/WebCore/loader/COEPInheritenceViolationReportBody.h b/Source/WebCore/loader/COEPInheritenceViolationReportBody.h index e7d88653eb81..54c815a8cd55 100644 --- a/Source/WebCore/loader/COEPInheritenceViolationReportBody.h +++ b/Source/WebCore/loader/COEPInheritenceViolationReportBody.h @@ -45,6 +45,8 @@ class COEPInheritenceViolationReportBody : public ReportBody { friend struct IPC::ArgumentCoder; COEPInheritenceViolationReportBody(COEPDisposition, const URL& blockedURL, const String& type); + ViolationReportType reportBodyType() const final { return ViolationReportType::COEPInheritenceViolation; } + COEPDisposition m_disposition; URL m_blockedURL; String m_type; diff --git a/Source/WebCore/loader/CORPViolationReportBody.cpp b/Source/WebCore/loader/CORPViolationReportBody.cpp index 62e4fd18eb2c..4719195da2d6 100644 --- a/Source/WebCore/loader/CORPViolationReportBody.cpp +++ b/Source/WebCore/loader/CORPViolationReportBody.cpp @@ -38,8 +38,7 @@ Ref CORPViolationReportBody::create(COEPDisposition dis } CORPViolationReportBody::CORPViolationReportBody(COEPDisposition disposition, const URL& blockedURL, FetchOptions::Destination destination) - : ReportBody(ViolationReportType::CORPViolation) - , m_disposition(disposition) + : m_disposition(disposition) , m_blockedURL(blockedURL) , m_destination(destination) { diff --git a/Source/WebCore/loader/CORPViolationReportBody.h b/Source/WebCore/loader/CORPViolationReportBody.h index a3569a31ea3d..23f6dc9a82a0 100644 --- a/Source/WebCore/loader/CORPViolationReportBody.h +++ b/Source/WebCore/loader/CORPViolationReportBody.h @@ -47,6 +47,8 @@ class CORPViolationReportBody : public ReportBody { friend struct IPC::ArgumentCoder; CORPViolationReportBody(COEPDisposition, const URL& blockedURL, FetchOptions::Destination); + ViolationReportType reportBodyType() const final { return ViolationReportType::CORPViolation; } + COEPDisposition m_disposition; URL m_blockedURL; FetchOptions::Destination m_destination; diff --git a/Source/WebCore/page/csp/CSPViolationReportBody.cpp b/Source/WebCore/page/csp/CSPViolationReportBody.cpp index 2f4681ce7086..6e351f0b29ff 100644 --- a/Source/WebCore/page/csp/CSPViolationReportBody.cpp +++ b/Source/WebCore/page/csp/CSPViolationReportBody.cpp @@ -39,8 +39,7 @@ using Init = SecurityPolicyViolationEventInit; WTF_MAKE_ISO_ALLOCATED_IMPL(CSPViolationReportBody); CSPViolationReportBody::CSPViolationReportBody(Init&& init) - : ReportBody(ViolationReportType::ContentSecurityPolicy) - , m_documentURL(WTFMove(init.documentURI)) + : m_documentURL(WTFMove(init.documentURI)) , m_referrer(init.referrer.isNull() ? emptyString() : WTFMove(init.referrer)) , m_blockedURL(WTFMove(init.blockedURI)) , m_effectiveDirective(WTFMove(init.effectiveDirective)) @@ -55,8 +54,7 @@ CSPViolationReportBody::CSPViolationReportBody(Init&& init) } CSPViolationReportBody::CSPViolationReportBody(String&& documentURL, String&& referrer, String&& blockedURL, String&& effectiveDirective, String&& originalPolicy, String&& sourceFile, String&& sample, SecurityPolicyViolationEventDisposition disposition, unsigned short statusCode, unsigned long lineNumber, unsigned long columnNumber) - : ReportBody(ViolationReportType::ContentSecurityPolicy) - , m_documentURL(WTFMove(documentURL)) + : m_documentURL(WTFMove(documentURL)) , m_referrer(WTFMove(referrer)) , m_blockedURL(WTFMove(blockedURL)) , m_effectiveDirective(WTFMove(effectiveDirective)) diff --git a/Source/WebCore/page/csp/CSPViolationReportBody.h b/Source/WebCore/page/csp/CSPViolationReportBody.h index 8725c2579989..30308e603eb4 100644 --- a/Source/WebCore/page/csp/CSPViolationReportBody.h +++ b/Source/WebCore/page/csp/CSPViolationReportBody.h @@ -64,6 +64,8 @@ class CSPViolationReportBody final : public ReportBody { CSPViolationReportBody(Init&&); CSPViolationReportBody(String&& documentURL, String&& referrer, String&& blockedURL, String&& effectiveDirective, String&& originalPolicy, String&& sourceFile, String&& sample, SecurityPolicyViolationEventDisposition, unsigned short statusCode, unsigned long lineNumber, unsigned long columnNumber); + ViolationReportType reportBodyType() const final { return ViolationReportType::ContentSecurityPolicy; } + const String m_documentURL; const String m_referrer; const String m_blockedURL; diff --git a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.serialization.in b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.serialization.in index e17a4a54ac4e..c83e9dd49417 100644 --- a/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.serialization.in +++ b/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.serialization.in @@ -31,6 +31,9 @@ class WebKit::NetworkLoadParameters { RefPtr topOrigin; RefPtr sourceOrigin; WTF::ProcessID parentPID; +#if HAVE(AUDIT_TOKEN) + [NotSerialized] std::optional networkProcessAuditToken; +#endif WebCore::ResourceRequest request; WebCore::ContentSniffingPolicy contentSniffingPolicy; @@ -43,8 +46,9 @@ class WebKit::NetworkLoadParameters { bool isMainFrameNavigation; bool isMainResourceNavigationForAnyFrame; WebCore::ShouldRelaxThirdPartyCookieBlocking shouldRelaxThirdPartyCookieBlocking; - + [NotSerialized] Vector> blobFileReferences; WebKit::PreconnectOnly shouldPreconnectOnly; + [NotSerialized] std::optional networkActivityTracker; std::optional isNavigatingToAppBoundDomain; bool hadMainFrameMainResourcePrivateRelayed; bool allowPrivacyProxy; diff --git a/Source/WebKit/Scripts/generate-serializers.py b/Source/WebKit/Scripts/generate-serializers.py index 92e112e63d14..a7a67240cc76 100755 --- a/Source/WebKit/Scripts/generate-serializers.py +++ b/Source/WebKit/Scripts/generate-serializers.py @@ -43,6 +43,7 @@ # BitField - work around the need for http://wg21.link/P0572 and don't check that the serialization order matches the memory layout. # Nullable - check if the member is truthy before serializing. # Validator - additional C++ to validate the value when decoding +# NotSerialized - member is present in structure but intentionally not serialized. class SerializedType(object): def __init__(self, struct_or_class, namespace, name, parent_class_name, members, condition, attributes, other_metadata=None): @@ -117,6 +118,9 @@ def can_assert_member_order_is_correct(self): return False return True + def serialized_members(self): + return list(filter(lambda member: 'NotSerialized' not in member.attributes, self.members)) + class SerializedEnum(object): def __init__(self, namespace, name, underlying_type, valid_values, condition, attributes): @@ -348,10 +352,10 @@ def resolve_inheritance(serialized_types): return result -def check_type_members(type): +def check_type_members(type, checking_parent_class): result = [] if type.parent_class is not None: - result = result + check_type_members(type.parent_class) + result = check_type_members(type.parent_class, True) for member in type.members: if member.condition is not None: result.append('#if ' + member.condition) @@ -359,9 +363,19 @@ def check_type_members(type): if member.condition is not None: result.append('#endif') if type.can_assert_member_order_is_correct(): + # FIXME: Add this check for types with parent classes, too. + if type.parent_class is None and not checking_parent_class: + result.append(' struct ShouldBeSameSizeAs' + type.name + ' : public VirtualTableAndRefCountOverhead, ' + ('true' if type.return_ref else 'false') + '> {') + for member in type.members: + if member.condition is not None: + result.append('#if ' + member.condition) + result.append(' ' + member.type + ' ' + member.name + (' : 1' if 'BitField' in member.attributes else '') + ';') + if member.condition is not None: + result.append('#endif') + result.append(' };') + result.append(' static_assert(sizeof(ShouldBeSameSizeAs' + type.name + ') == sizeof(' + type.namespace_and_name() + '));') result.append(' static_assert(MembersInCorrectOrder<0') - for i in range(len(type.members)): - member = type.members[i] + for member in type.members: if 'BitField' in member.attributes: continue if member.condition is not None: @@ -377,7 +391,7 @@ def encode_type(type): result = [] if type.parent_class is not None: result = result + encode_type(type.parent_class) - for member in type.members: + for member in type.serialized_members(): if member.condition is not None: result.append('#if ' + member.condition) if 'Nullable' in member.attributes: @@ -409,7 +423,7 @@ def decode_type(type): result.append(' return std::nullopt;') result.append('') - for member in type.members: + for member in type.serialized_members(): if member.condition is not None: result.append('#if ' + member.condition) sanitized_variable_name = sanitize_string_for_variable_name(member.name) @@ -502,11 +516,12 @@ def construct_type(type, indentation): result = result + construct_type(type.parent_class, indentation + 1) if len(type.members) != 0: result[-1] += ',' - for i in range(len(type.members)): - member = type.members[i] - if type.members[i].condition is not None: + serialized_members = type.serialized_members() + for i in range(len(serialized_members)): + member = serialized_members[i] + if member.condition is not None: result.append('#if ' + member.condition) - result.append(indent(indentation + 1) + 'WTFMove(*' + sanitize_string_for_variable_name(member.name) + ')' + ('' if i == len(type.members) - 1 else ',')) + result.append(indent(indentation + 1) + 'WTFMove(*' + sanitize_string_for_variable_name(member.name) + ')' + ('' if i == len(serialized_members) - 1 else ',')) if member.condition is not None: result.append('#endif') if type.create_using or type.return_ref: @@ -529,6 +544,35 @@ def generate_impl(serialized_types, serialized_enums, headers): result.append(' static constexpr bool value = firstOffset > secondOffset ? false : MembersInCorrectOrder::value;') result.append('};') result.append('') + result.append('template struct VirtualTableAndRefCountOverhead;') + result.append('template<> struct VirtualTableAndRefCountOverhead {') + result.append(' virtual ~VirtualTableAndRefCountOverhead() { }') + result.append(' unsigned refCount;') + result.append('#if ASSERT_ENABLED') + result.append(' bool m_isOwnedByMainThread;') + result.append(' bool m_areThreadingChecksEnabled;') + result.append('#endif') + result.append('#if CHECK_REF_COUNTED_LIFECYCLE') + result.append(' bool m_deletionHasBegun;') + result.append(' bool m_adoptionIsRequired;') + result.append('#endif') + result.append('};') + result.append('template<> struct VirtualTableAndRefCountOverhead {') + result.append(' unsigned refCount;') + result.append('#if ASSERT_ENABLED') + result.append(' bool m_isOwnedByMainThread;') + result.append(' bool m_areThreadingChecksEnabled;') + result.append('#endif') + result.append('#if CHECK_REF_COUNTED_LIFECYCLE') + result.append(' bool m_deletionHasBegun;') + result.append(' bool m_adoptionIsRequired;') + result.append('#endif') + result.append('};') + result.append('template<> struct VirtualTableAndRefCountOverhead {') + result.append(' virtual ~VirtualTableAndRefCountOverhead() { }') + result.append('};') + result.append('template<> struct VirtualTableAndRefCountOverhead { };') + result.append('') # GCC is less generous with its interpretation of "Use of the offsetof macro with a # type other than a standard-layout class is conditionally-supported". result.append('#if COMPILER(GCC)') @@ -564,7 +608,7 @@ def generate_impl(serialized_types, serialized_enums, headers): result.append('void ArgumentCoder<' + type.namespace_and_name() + '>::encode(' + encoder + '& encoder, const ' + type.namespace_and_name() + '& instance)') result.append('{') if not type.members_are_subclasses: - result = result + check_type_members(type) + result = result + check_type_members(type, False) result = result + encode_type(type) result.append('}') result.append('') @@ -577,7 +621,7 @@ def generate_impl(serialized_types, serialized_enums, headers): if not type.members_are_subclasses: if type.populate_from_empty_constructor: result.append(' ' + type.namespace_and_name() + ' result;') - for member in type.members: + for member in type.serialized_members(): if member.condition is not None: result.append('#if ' + member.condition) result.append(' result.' + member.name + ' = WTFMove(*' + member.name + ');') @@ -692,15 +736,18 @@ def generate_serialized_type_info(serialized_types, serialized_enums, headers, t result.append(' { "std::variant<' + ', '.join([member.namespace + '::' + member.name for member in type.members]) + '>"_s, "subclasses"_s }') result.append(' } },') continue - for i in range(len(type.members)): + + serialized_members = type.serialized_members() + for i in range(len(serialized_members)): + member = type.members[i] if i == 0: result.append(' {') - if 'Nullable' in type.members[i].attributes: - result.append(' "std::optional<' + type.members[i].type + '>"_s,') + if 'Nullable' in member.attributes: + result.append(' "std::optional<' + member.type + '>"_s,') else: - result.append(' "' + type.members[i].type + '"_s,') - result.append(' "' + type.members[i].name + '"_s') - if i == len(type.members) - 1: + result.append(' "' + member.type + '"_s,') + result.append(' "' + member.name + '"_s') + if i == len(serialized_members) - 1: result.append(' }') else: result.append(' }, {') diff --git a/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp b/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp index 99b739de603d..c79936aac950 100644 --- a/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp +++ b/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp @@ -31,13 +31,42 @@ template st static constexpr bool value = firstOffset > secondOffset ? false : MembersInCorrectOrder::value; }; +template struct VirtualTableAndRefCountOverhead; +template<> struct VirtualTableAndRefCountOverhead { + virtual ~VirtualTableAndRefCountOverhead() { } + unsigned refCount; +#if ASSERT_ENABLED + bool m_isOwnedByMainThread; + bool m_areThreadingChecksEnabled; +#endif +#if CHECK_REF_COUNTED_LIFECYCLE + bool m_deletionHasBegun; + bool m_adoptionIsRequired; +#endif +}; +template<> struct VirtualTableAndRefCountOverhead { + unsigned refCount; +#if ASSERT_ENABLED + bool m_isOwnedByMainThread; + bool m_areThreadingChecksEnabled; +#endif +#if CHECK_REF_COUNTED_LIFECYCLE + bool m_deletionHasBegun; + bool m_adoptionIsRequired; +#endif +}; +template<> struct VirtualTableAndRefCountOverhead { + virtual ~VirtualTableAndRefCountOverhead() { } +}; +template<> struct VirtualTableAndRefCountOverhead { }; + #if COMPILER(GCC) IGNORE_WARNINGS_BEGIN("invalid-offsetof") #endif +#include "CommonHeader.h" #if ENABLE(TEST_FEATURE) #include "CommonHeader.h" #endif -#include "CommonHeader.h" #if ENABLE(TEST_FEATURE) #include "FirstMemberType.h" #endif @@ -76,6 +105,14 @@ void ArgumentCoder::encode(Encoder& encoder static_assert(std::is_same_v, SecondMemberType>); #endif static_assert(std::is_same_v, RetainPtr>); + struct ShouldBeSameSizeAsStructName : public VirtualTableAndRefCountOverhead, false> { + FirstMemberType firstMemberName; +#if ENABLE(SECOND_MEMBER) + SecondMemberType secondMemberName; +#endif + RetainPtr nullableTestMember; + }; + static_assert(sizeof(ShouldBeSameSizeAsStructName) == sizeof(Namespace::Subnamespace::StructName)); static_assert(MembersInCorrectOrder<0 , offsetof(Namespace::Subnamespace::StructName, firstMemberName) #if ENABLE(SECOND_MEMBER) @@ -99,6 +136,14 @@ void ArgumentCoder::encode(OtherEncoder& en static_assert(std::is_same_v, SecondMemberType>); #endif static_assert(std::is_same_v, RetainPtr>); + struct ShouldBeSameSizeAsStructName : public VirtualTableAndRefCountOverhead, false> { + FirstMemberType firstMemberName; +#if ENABLE(SECOND_MEMBER) + SecondMemberType secondMemberName; +#endif + RetainPtr nullableTestMember; + }; + static_assert(sizeof(ShouldBeSameSizeAsStructName) == sizeof(Namespace::Subnamespace::StructName)); static_assert(MembersInCorrectOrder<0 , offsetof(Namespace::Subnamespace::StructName, firstMemberName) #if ENABLE(SECOND_MEMBER) @@ -158,6 +203,13 @@ void ArgumentCoder::encode(Encoder& encoder, const Namesp static_assert(std::is_same_v, int>); static_assert(std::is_same_v, bool>); static_assert(std::is_same_v, RetainPtr>); + struct ShouldBeSameSizeAsOtherClass : public VirtualTableAndRefCountOverhead, false> { + bool isNull; + int a; + bool b : 1; + RetainPtr dataDetectorResults; + }; + static_assert(sizeof(ShouldBeSameSizeAsOtherClass) == sizeof(Namespace::OtherClass)); static_assert(MembersInCorrectOrder<0 , offsetof(Namespace::OtherClass, isNull) , offsetof(Namespace::OtherClass, a) @@ -266,6 +318,16 @@ void ArgumentCoder::encode(Encoder& encoder #if CONDITION_AROUND_M_TYPE_AND_M_VALUE static_assert(std::is_same_v, OtherMemberType>); #endif + struct ShouldBeSameSizeAsEmptyConstructorNullable : public VirtualTableAndRefCountOverhead, false> { + bool m_isNull; +#if CONDITION_AROUND_M_TYPE_AND_M_VALUE + MemberType m_type; +#endif +#if CONDITION_AROUND_M_TYPE_AND_M_VALUE + OtherMemberType m_value; +#endif + }; + static_assert(sizeof(ShouldBeSameSizeAsEmptyConstructorNullable) == sizeof(Namespace::EmptyConstructorNullable)); static_assert(MembersInCorrectOrder<0 , offsetof(Namespace::EmptyConstructorNullable, m_isNull) #if CONDITION_AROUND_M_TYPE_AND_M_VALUE @@ -317,6 +379,10 @@ std::optional ArgumentCoder::encode(Encoder& encoder, const WithoutNamespace& instance) { static_assert(std::is_same_v, int>); + struct ShouldBeSameSizeAsWithoutNamespace : public VirtualTableAndRefCountOverhead, false> { + int a; + }; + static_assert(sizeof(ShouldBeSameSizeAsWithoutNamespace) == sizeof(WithoutNamespace)); static_assert(MembersInCorrectOrder<0 , offsetof(WithoutNamespace, a) >::value); @@ -340,6 +406,10 @@ std::optional ArgumentCoder::decode(Decoder& void ArgumentCoder::encode(Encoder& encoder, const WithoutNamespaceWithAttributes& instance) { static_assert(std::is_same_v, int>); + struct ShouldBeSameSizeAsWithoutNamespaceWithAttributes : public VirtualTableAndRefCountOverhead, false> { + int a; + }; + static_assert(sizeof(ShouldBeSameSizeAsWithoutNamespaceWithAttributes) == sizeof(WithoutNamespaceWithAttributes)); static_assert(MembersInCorrectOrder<0 , offsetof(WithoutNamespaceWithAttributes, a) >::value); @@ -349,6 +419,10 @@ void ArgumentCoder::encode(Encoder& encoder, con void ArgumentCoder::encode(OtherEncoder& encoder, const WithoutNamespaceWithAttributes& instance) { static_assert(std::is_same_v, int>); + struct ShouldBeSameSizeAsWithoutNamespaceWithAttributes : public VirtualTableAndRefCountOverhead, false> { + int a; + }; + static_assert(sizeof(ShouldBeSameSizeAsWithoutNamespaceWithAttributes) == sizeof(WithoutNamespaceWithAttributes)); static_assert(MembersInCorrectOrder<0 , offsetof(WithoutNamespaceWithAttributes, a) >::value); @@ -474,6 +548,10 @@ std::optional ArgumentCoder::decode(Decoder& decoder void ArgumentCoder::encode(Encoder& encoder, const WTF::CreateUsingClass& instance) { static_assert(std::is_same_v, double>); + struct ShouldBeSameSizeAsCreateUsingClass : public VirtualTableAndRefCountOverhead, false> { + double value; + }; + static_assert(sizeof(ShouldBeSameSizeAsCreateUsingClass) == sizeof(WTF::CreateUsingClass)); static_assert(MembersInCorrectOrder<0 , offsetof(WTF::CreateUsingClass, value) >::value); @@ -539,6 +617,11 @@ void ArgumentCoder::encode(Encoder& encoder, const Nul { static_assert(std::is_same_v, RetainPtr>); static_assert(std::is_same_v, RetainPtr>); + struct ShouldBeSameSizeAsNullableSoftLinkedMember : public VirtualTableAndRefCountOverhead, false> { + RetainPtr firstMember; + RetainPtr secondMember; + }; + static_assert(sizeof(ShouldBeSameSizeAsNullableSoftLinkedMember) == sizeof(NullableSoftLinkedMember)); static_assert(MembersInCorrectOrder<0 , offsetof(NullableSoftLinkedMember, firstMember) , offsetof(NullableSoftLinkedMember, secondMember) @@ -649,6 +732,10 @@ std::optional> ArgumentCoder::encode(Encoder& encoder, const Namespace::ConditionalCommonClass& instance) { static_assert(std::is_same_v, int>); + struct ShouldBeSameSizeAsConditionalCommonClass : public VirtualTableAndRefCountOverhead, false> { + int value; + }; + static_assert(sizeof(ShouldBeSameSizeAsConditionalCommonClass) == sizeof(Namespace::ConditionalCommonClass)); static_assert(MembersInCorrectOrder<0 , offsetof(Namespace::ConditionalCommonClass, value) >::value); @@ -671,48 +758,59 @@ std::optional ArgumentCoder::encode(Encoder& encoder, const Namesapce::CommonClass& instance) +void ArgumentCoder::encode(Encoder& encoder, const Namespace::CommonClass& instance) { static_assert(std::is_same_v, int>); + struct ShouldBeSameSizeAsCommonClass : public VirtualTableAndRefCountOverhead, false> { + int value; + }; + static_assert(sizeof(ShouldBeSameSizeAsCommonClass) == sizeof(Namespace::CommonClass)); static_assert(MembersInCorrectOrder<0 - , offsetof(Namesapce::CommonClass, value) + , offsetof(Namespace::CommonClass, value) >::value); encoder << instance.value; } -std::optional ArgumentCoder::decode(Decoder& decoder) +std::optional ArgumentCoder::decode(Decoder& decoder) { auto value = decoder.decode(); if (!value) return std::nullopt; return { - Namesapce::CommonClass { + Namespace::CommonClass { WTFMove(*value) } }; } -void ArgumentCoder::encode(Encoder& encoder, const Namesapce::AnotherCommonClass& instance) +void ArgumentCoder::encode(Encoder& encoder, const Namespace::AnotherCommonClass& instance) { static_assert(std::is_same_v, int>); + static_assert(std::is_same_v, double>); + struct ShouldBeSameSizeAsAnotherCommonClass : public VirtualTableAndRefCountOverhead, true> { + int value; + double notSerialized; + }; + static_assert(sizeof(ShouldBeSameSizeAsAnotherCommonClass) == sizeof(Namespace::AnotherCommonClass)); static_assert(MembersInCorrectOrder<0 - , offsetof(Namesapce::AnotherCommonClass, value) + , offsetof(Namespace::AnotherCommonClass, value) + , offsetof(Namespace::AnotherCommonClass, notSerialized) >::value); encoder << instance.value; } -std::optional ArgumentCoder::decode(Decoder& decoder) +std::optional> ArgumentCoder::decode(Decoder& decoder) { auto value = decoder.decode(); if (!value) return std::nullopt; return { - Namesapce::AnotherCommonClass { + Namespace::AnotherCommonClass::create( WTFMove(*value) - } + ) }; } diff --git a/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h b/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h index 6a38d0f5da4b..7e1caf617b27 100644 --- a/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h +++ b/Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h @@ -59,8 +59,8 @@ namespace WebCore { class TimingFunction; } #if ENABLE(TEST_FEATURE) namespace Namespace { class ConditionalCommonClass; } #endif -namespace Namesapce { class CommonClass; } -namespace Namesapce { class AnotherCommonClass; } +namespace Namespace { class CommonClass; } +namespace Namespace { class AnotherCommonClass; } namespace IPC { @@ -144,14 +144,14 @@ template<> struct ArgumentCoder { }; #endif -template<> struct ArgumentCoder { - static void encode(Encoder&, const Namesapce::CommonClass&); - static std::optional decode(Decoder&); +template<> struct ArgumentCoder { + static void encode(Encoder&, const Namespace::CommonClass&); + static std::optional decode(Decoder&); }; -template<> struct ArgumentCoder { - static void encode(Encoder&, const Namesapce::AnotherCommonClass&); - static std::optional decode(Decoder&); +template<> struct ArgumentCoder { + static void encode(Encoder&, const Namespace::AnotherCommonClass&); + static std::optional> decode(Decoder&); }; } // namespace IPC diff --git a/Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp b/Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp index 28c38080f6b7..5165f9fcba59 100644 --- a/Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp +++ b/Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp @@ -25,10 +25,10 @@ #include "config.h" #include "SerializedTypeInfo.h" +#include "CommonHeader.h" #if ENABLE(TEST_FEATURE) #include "CommonHeader.h" #endif -#include "CommonHeader.h" #if ENABLE(TEST_FEATURE) #include "FirstMemberType.h" #endif @@ -185,13 +185,13 @@ Vector allSerializedTypes() "value"_s } } }, - { "Namesapce::CommonClass"_s, { + { "Namespace::CommonClass"_s, { { "int"_s, "value"_s } } }, - { "Namesapce::AnotherCommonClass"_s, { + { "Namespace::AnotherCommonClass"_s, { { "int"_s, "value"_s diff --git a/Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in b/Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in index 5e91ac95099d..4d512874240c 100644 --- a/Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in +++ b/Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in @@ -147,11 +147,12 @@ headers: "CommonHeader.h" #endif headers: "CommonHeader.h" -[CustomHeader] class Namesapce::CommonClass { +[CustomHeader] class Namespace::CommonClass { int value; } headers: "CommonHeader.h" -[CustomHeader] class Namesapce::AnotherCommonClass { +[CustomHeader, RefCounted] class Namespace::AnotherCommonClass { int value; + [NotSerialized] double notSerialized; } diff --git a/Source/WebKit/Shared/SessionState.serialization.in b/Source/WebKit/Shared/SessionState.serialization.in index 567acff59f2a..93e9aa61428e 100644 --- a/Source/WebKit/Shared/SessionState.serialization.in +++ b/Source/WebKit/Shared/SessionState.serialization.in @@ -80,7 +80,9 @@ header: "SessionState.h" WebKit::PageState pageState; bool hasCachedPage; - # snapshot is not serialized. +#if PLATFORM(COCOA) || PLATFORM(GTK) + [NotSerialized] RefPtr snapshot; +#endif }; [CustomHeader] struct WebKit::BackForwardListState { diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in index e87b3b980a68..f154a4ea19e9 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in @@ -468,6 +468,7 @@ struct WebCore::ShareData { String title; String text; String url; + [NotSerialized] Vector> files; }; enum class WebCore::ShareDataOriginator : bool @@ -562,7 +563,8 @@ class WebCore::PrivateClickMeasurement { std::optional sourceRegistrableDomain; std::optional ephemeralDestinationNonce; std::optional destinationSite; -# destinationUnlinkableToken and destinationSecretToken are not serialized. + [NotSerialized] std::optional destinationUnlinkableToken; + [NotSerialized] std::optional destinationSecretToken; } [CustomHeader] struct WebCore::PCM::AttributionTimeToSendData { @@ -995,6 +997,7 @@ struct WebCore::WebLockManagerSnapshot { [LegacyPopulateFromEmptyConstructor] struct WebCore::AuthenticationExtensionsClientInputs { String appid; + [NotSerialized] bool credProps; std::optional largeBlob; } @@ -1080,6 +1083,7 @@ struct WebCore::PublicKeyCredentialRequestOptions { Vector allowCredentials; WebCore::UserVerificationRequirement userVerification; std::optional extensions; + [NotSerialized] std::optional authenticatorAttachment; #endif // ENABLE(WEB_AUTHN) }; @@ -1423,6 +1427,10 @@ struct WebCore::WindowFeatures { bool fullscreen; bool dialog; + [NotSerialized] bool noopener; + [NotSerialized] bool noreferrer; + + [NotSerialized] Vector additionalFeatures; }; [Nested] enum class WebCore::CompositionUnderlineColor : bool @@ -1976,6 +1984,7 @@ header: }; [RefCounted] class WebCore::IdentityTransformOperation { + [NotSerialized] WebCore::TransformOperation::Type type(); } [RefCounted] class WebCore::TranslateTransformOperation { @@ -2106,6 +2115,7 @@ struct WebCore::GraphicsContextGLAttributes { bool xrCompatible; #endif bool failPlatformContextCreationForTesting; + [NotSerialized] unsigned remoteIPCBufferSizeLog2ForTesting; }; #endif // ENABLE(GPU_PROCESS) && ENABLE(WEBGL) @@ -4395,6 +4405,8 @@ header: bool madeHTTPS; bool blockedCookies; bool hasNotifications; + [NotSerialized] Vector modifyHeadersActions; + [NotSerialized] Vector> redirectActions; }; struct WebCore::ContentRuleListResults {