diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml index 63a84c9cd0d0f9..d0db9830e3e599 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.ComponentModel.TypeConverter/src/ILLink/ILLink.Suppressions.xml @@ -289,5 +289,17 @@ member M:System.ComponentModel.BindingList`1.get_ItemTypeHasDefaultConstructor + + ILLink + IL2026 + member + M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Deserialize(System.IO.Stream,System.String,System.ComponentModel.Design.RuntimeLicenseContext) + + + ILLink + IL2026 + member + M:System.ComponentModel.Design.DesigntimeLicenseContextSerializer.Serialize(System.IO.Stream,System.String,System.ComponentModel.Design.DesigntimeLicenseContext) + diff --git a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml index 7b29974c298e81..d5d68da0e626ee 100644 --- a/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Data.Common/src/ILLink/ILLink.Suppressions.xml @@ -133,5 +133,17 @@ member M:System.Data.DataColumn.get_DefaultValue + + ILLink + IL2026 + member + M:System.Data.DataSet.DeserializeDataSetSchema(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,System.Data.SerializationFormat,System.Data.SchemaSerializationMode) + + + ILLink + IL2026 + member + M:System.Data.DataSet.SerializeDataSet(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,System.Data.SerializationFormat) + - \ No newline at end of file + diff --git a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.cs b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.cs index dc9d5f71b9f3b5..ecfda2d0efd1f3 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/ref/System.Runtime.Serialization.Formatters.cs @@ -16,10 +16,12 @@ protected Formatter() { } public abstract System.Runtime.Serialization.StreamingContext Context { get; set; } public abstract System.Runtime.Serialization.ISurrogateSelector? SurrogateSelector { get; set; } [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] public abstract object Deserialize(System.IO.Stream serializationStream); protected virtual object? GetNext(out long objID) { throw null; } protected virtual long Schedule(object? obj) { throw null; } [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] public abstract void Serialize(System.IO.Stream serializationStream, object graph); protected abstract void WriteArray(object obj, string name, System.Type memberType); protected abstract void WriteBoolean(bool val, string name); @@ -74,12 +76,13 @@ public static partial class FormatterServices { public static void CheckTypeSecurity(System.Type t, System.Runtime.Serialization.Formatters.TypeFilterLevel securityLevel) { } public static object?[] GetObjectData(object obj, System.Reflection.MemberInfo[] members) { throw null; } - public static object GetSafeUninitializedObject(System.Type type) { throw null; } - public static System.Reflection.MemberInfo[] GetSerializableMembers(System.Type type) { throw null; } - public static System.Reflection.MemberInfo[] GetSerializableMembers(System.Type type, System.Runtime.Serialization.StreamingContext context) { throw null; } + public static object GetSafeUninitializedObject([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type) { throw null; } + public static System.Reflection.MemberInfo[] GetSerializableMembers([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type) { throw null; } + public static System.Reflection.MemberInfo[] GetSerializableMembers([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type, System.Runtime.Serialization.StreamingContext context) { throw null; } public static System.Runtime.Serialization.ISerializationSurrogate GetSurrogateForCyclicalReference(System.Runtime.Serialization.ISerializationSurrogate innerSurrogate) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public static System.Type? GetTypeFromAssembly(System.Reflection.Assembly assem, string name) { throw null; } - public static object GetUninitializedObject(System.Type type) { throw null; } + public static object GetUninitializedObject([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type) { throw null; } public static object PopulateObjectMembers(object obj, System.Reflection.MemberInfo[] members, object?[] data) { throw null; } } public partial interface IFormatter @@ -88,8 +91,10 @@ public partial interface IFormatter System.Runtime.Serialization.StreamingContext Context { get; set; } System.Runtime.Serialization.ISurrogateSelector? SurrogateSelector { get; set; } [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] object Deserialize(System.IO.Stream serializationStream); [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] void Serialize(System.IO.Stream serializationStream, object graph); } public partial interface ISerializationSurrogate @@ -112,17 +117,23 @@ public ObjectIDGenerator() { } public partial class ObjectManager { public ObjectManager(System.Runtime.Serialization.ISurrogateSelector? selector, System.Runtime.Serialization.StreamingContext context) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public virtual void DoFixups() { } public virtual object? GetObject(long objectID) { throw null; } public virtual void RaiseDeserializationEvent() { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public void RaiseOnDeserializingEvent(object obj) { } public virtual void RecordArrayElementFixup(long arrayToBeFixed, int index, long objectRequired) { } public virtual void RecordArrayElementFixup(long arrayToBeFixed, int[] indices, long objectRequired) { } public virtual void RecordDelayedFixup(long objectToBeFixed, string memberName, long objectRequired) { } public virtual void RecordFixup(long objectToBeFixed, System.Reflection.MemberInfo member, long objectRequired) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public virtual void RegisterObject(object obj, long objectID) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public void RegisterObject(object obj, long objectID, System.Runtime.Serialization.SerializationInfo info) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public void RegisterObject(object obj, long objectID, System.Runtime.Serialization.SerializationInfo? info, long idOfContainingObj, System.Reflection.MemberInfo? member) { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public void RegisterObject(object obj, long objectID, System.Runtime.Serialization.SerializationInfo? info, long idOfContainingObj, System.Reflection.MemberInfo? member, int[]? arrayIndex) { } } public abstract partial class SerializationBinder @@ -135,6 +146,7 @@ public sealed partial class SerializationObjectManager { public SerializationObjectManager(System.Runtime.Serialization.StreamingContext context) { } public void RaiseOnSerializedEvent() { } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("SerializationObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered.")] public void RegisterObject(object obj) { } } public partial class SurrogateSelector : System.Runtime.Serialization.ISurrogateSelector @@ -184,8 +196,10 @@ public BinaryFormatter(System.Runtime.Serialization.ISurrogateSelector? selector public System.Runtime.Serialization.ISurrogateSelector? SurrogateSelector { get { throw null; } set { } } public System.Runtime.Serialization.Formatters.FormatterTypeStyle TypeFormat { get { throw null; } set { } } [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] public object Deserialize(System.IO.Stream serializationStream) { throw null; } [System.ObsoleteAttribute("BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.", DiagnosticId = "SYSLIB0011", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered.")] public void Serialize(System.IO.Stream serializationStream, object graph) { } } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Suppressions.xml deleted file mode 100644 index 9b389862e0c92f..00000000000000 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/ILLink/ILLink.Suppressions.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - ILLink - IL2026 - member - M:System.Runtime.Serialization.Formatters.Binary.ObjectReader.TopLevelAssemblyTypeResolver.ResolveType(System.Reflection.Assembly,System.String,System.Boolean) - - - ILLink - IL2026 - member - M:System.Runtime.Serialization.FormatterServices.GetTypeFromAssembly(System.Reflection.Assembly,System.String) - - - ILLink - IL2057 - member - M:System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetSimplyNamedTypeFromAssembly(System.Reflection.Assembly,System.String,System.Type@) - - - ILLink - IL2067 - member - M:System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(System.Type) - - - ILLink - IL2070 - member - M:System.Runtime.Serialization.FormatterServices.GetSerializableFields(System.Type) - - - ILLink - IL2070 - member - M:System.Runtime.Serialization.ObjectManager.GetDeserializationConstructor(System.Type) - - - ILLink - IL2070 - member - M:System.Runtime.Serialization.SerializationEvents.GetMethodsWithAttribute(System.Type,System.Type) - - - ILLink - IL2075 - member - M:System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(System.Type) - - - ILLink - IL2075 - member - M:System.Runtime.Serialization.ObjectManager.DoValueTypeFixup(System.Reflection.FieldInfo,System.Runtime.Serialization.ObjectHolder,System.Object) - - - ILLink - IL2077 - member - M:System.Runtime.Serialization.Formatters.Binary.ObjectReader.ParseObject(System.Runtime.Serialization.Formatters.Binary.ParseRecord) - - - \ No newline at end of file diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatter.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatter.cs index 5d97328d8569db..8748e6901547de 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatter.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatter.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.IO; -using System.Globalization; using System.Collections; -using System.Reflection; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO; namespace System.Runtime.Serialization { @@ -21,6 +21,7 @@ protected Formatter() } [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public abstract object Deserialize(Stream serializationStream); protected virtual object? GetNext(out long objID) @@ -61,6 +62,7 @@ protected virtual long Schedule(object? obj) } [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public abstract void Serialize(Stream serializationStream, object graph); protected abstract void WriteArray(object obj, string name, Type memberType); diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs index 3403898e2e2b37..b3f94a260d7c53 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters; @@ -16,7 +16,11 @@ public static class FormatterServices { private static readonly ConcurrentDictionary s_memberInfoTable = new ConcurrentDictionary(); - private static FieldInfo[] InternalGetSerializableMembers(Type type) + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "The Type is annotated with All, which will preserve base type fields.")] + private static FieldInfo[] InternalGetSerializableMembers( + // currently the only way to preserve base, non-public fields is to use All + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { Debug.Assert(type != null); @@ -79,7 +83,8 @@ private static FieldInfo[] InternalGetSerializableMembers(Type type) return typeMembers; } - private static FieldInfo[] GetSerializableFields(Type type) + private static FieldInfo[] GetSerializableFields( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) { // Get the list of all fields FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); @@ -156,12 +161,15 @@ private static bool GetParentTypes(Type parentType, out Type[]? parentTypes, out return unique; } - public static MemberInfo[] GetSerializableMembers(Type type) + public static MemberInfo[] GetSerializableMembers( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { return GetSerializableMembers(type, new StreamingContext(StreamingContextStates.All)); } - public static MemberInfo[] GetSerializableMembers(Type type, StreamingContext context) + public static MemberInfo[] GetSerializableMembers( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + StreamingContext context) { if (type == null) { @@ -189,7 +197,9 @@ public static object GetUninitializedObject( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type) => RuntimeHelpers.GetUninitializedObject(type); - public static object GetSafeUninitializedObject(Type type) => RuntimeHelpers.GetUninitializedObject(type); + public static object GetSafeUninitializedObject( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + Type type) => RuntimeHelpers.GetUninitializedObject(type); internal static void SerializationSetValue(MemberInfo fi, object? target, object? value) { @@ -294,6 +304,7 @@ public static ISerializationSurrogate GetSurrogateForCyclicalReference(ISerializ return new SurrogateForCyclicalReference(innerSurrogate); } + [RequiresUnreferencedCode("Types might be removed")] public static Type? GetTypeFromAssembly(Assembly assem, string name) { if (assem == null) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs index 939b78ad9535dc..8d3e437a0b5c5c 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.Core.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; namespace System.Runtime.Serialization.Formatters.Binary @@ -8,6 +9,7 @@ namespace System.Runtime.Serialization.Formatters.Binary public sealed partial class BinaryFormatter : IFormatter { [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public object Deserialize(Stream serializationStream) { // don't refactor the 'throw' into a helper method; linker will have difficulty trimming @@ -58,6 +60,7 @@ public object Deserialize(Stream serializationStream) } [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public void Serialize(Stream serializationStream, object graph) { // don't refactor the 'throw' into a helper method; linker will have difficulty trimming diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs index 4d56deea06fafb..59970dabe4a6b1 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryFormatter.PlatformNotSupported.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; namespace System.Runtime.Serialization.Formatters.Binary @@ -8,10 +9,12 @@ namespace System.Runtime.Serialization.Formatters.Binary public sealed partial class BinaryFormatter : IFormatter { [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public object Deserialize(Stream serializationStream) => throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationDisallowed); [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(IFormatter.RequiresUnreferencedCodeMessage)] public void Serialize(Stream serializationStream, object graph) => throw new PlatformNotSupportedException(SR.BinaryFormatter_SerializationDisallowed); } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectInfo.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectInfo.cs index 64f4e6ddcd830d..7d9036a907ebfc 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectInfo.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectInfo.cs @@ -1,10 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Threading; using System.Collections.Generic; -using System.Reflection; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Threading; namespace System.Runtime.Serialization.Formatters.Binary { @@ -15,6 +16,7 @@ internal sealed class WriteObjectInfo { internal int _objectInfoId; internal object? _obj; + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] internal Type? _objectType; internal bool _isSi; @@ -65,6 +67,7 @@ private void InternalInit() _binderAssemblyString = null; } + [RequiresUnreferencedCode("It isn't possible to statically get the Type of object")] internal static WriteObjectInfo Serialize(object obj, ISurrogateSelector? surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder? binder) { WriteObjectInfo woi = GetObjectInfo(serObjectInfoInit); @@ -73,6 +76,7 @@ internal static WriteObjectInfo Serialize(object obj, ISurrogateSelector? surrog } // Write constructor + [RequiresUnreferencedCode("It isn't possible to statically get the Type of object")] internal void InitSerialize(object obj, ISurrogateSelector? surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder? binder) { _context = context; @@ -118,7 +122,13 @@ internal void InitSerialize(object obj, ISurrogateSelector? surrogateSelector, S } } - internal static WriteObjectInfo Serialize(Type objectType, ISurrogateSelector? surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SerializationBinder? binder) + internal static WriteObjectInfo Serialize( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + SerObjectInfoInit serObjectInfoInit, + IFormatterConverter converter, + SerializationBinder? binder) { WriteObjectInfo woi = GetObjectInfo(serObjectInfoInit); woi.InitSerialize(objectType, surrogateSelector, context, serObjectInfoInit, converter, binder); @@ -126,7 +136,13 @@ internal static WriteObjectInfo Serialize(Type objectType, ISurrogateSelector? s } // Write Constructor used for array types or null members - internal void InitSerialize(Type objectType, ISurrogateSelector? surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, SerializationBinder? binder) + internal void InitSerialize( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + SerObjectInfoInit serObjectInfoInit, + IFormatterConverter converter, + SerializationBinder? binder) { _objectType = objectType; _context = context; @@ -313,6 +329,7 @@ internal sealed class ReadObjectInfo internal int _objectInfoId; internal static int _readObjectInfoCounter; + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] internal Type? _objectType; internal ObjectManager? _objectManager; @@ -347,14 +364,28 @@ internal void PrepareForReuse() _lastPosition = 0; } - internal static ReadObjectInfo Create(Type objectType, ISurrogateSelector? surrogateSelector, StreamingContext context, ObjectManager? objectManager, SerObjectInfoInit? serObjectInfoInit, IFormatterConverter? converter, bool bSimpleAssembly) + internal static ReadObjectInfo Create( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + ObjectManager? objectManager, + SerObjectInfoInit? serObjectInfoInit, + IFormatterConverter? converter, + bool bSimpleAssembly) { ReadObjectInfo roi = GetObjectInfo(serObjectInfoInit); roi.Init(objectType, surrogateSelector, context, objectManager, serObjectInfoInit, converter, bSimpleAssembly); return roi; } - internal void Init(Type objectType, ISurrogateSelector? surrogateSelector, StreamingContext context, ObjectManager? objectManager, SerObjectInfoInit? serObjectInfoInit, IFormatterConverter? converter, bool bSimpleAssembly) + internal void Init( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + ObjectManager? objectManager, + SerObjectInfoInit? serObjectInfoInit, + IFormatterConverter? converter, + bool bSimpleAssembly) { _objectType = objectType; _objectManager = objectManager; @@ -366,14 +397,32 @@ internal void Init(Type objectType, ISurrogateSelector? surrogateSelector, Strea InitReadConstructor(objectType, surrogateSelector, context); } - internal static ReadObjectInfo Create(Type? objectType, string[] memberNames, Type[]? memberTypes, ISurrogateSelector? surrogateSelector, StreamingContext context, ObjectManager? objectManager, SerObjectInfoInit? serObjectInfoInit, IFormatterConverter? converter, bool bSimpleAssembly) + internal static ReadObjectInfo Create( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? objectType, + string[] memberNames, + Type[]? memberTypes, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + ObjectManager? objectManager, + SerObjectInfoInit? serObjectInfoInit, + IFormatterConverter? converter, + bool bSimpleAssembly) { ReadObjectInfo roi = GetObjectInfo(serObjectInfoInit); roi.Init(objectType, memberNames, memberTypes, surrogateSelector, context, objectManager, serObjectInfoInit, converter, bSimpleAssembly); return roi; } - internal void Init(Type? objectType, string[] memberNames, Type[]? memberTypes, ISurrogateSelector? surrogateSelector, StreamingContext context, ObjectManager? objectManager, SerObjectInfoInit? serObjectInfoInit, IFormatterConverter? converter, bool bSimpleAssembly) + internal void Init( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? objectType, + string[] memberNames, + Type[]? memberTypes, + ISurrogateSelector? surrogateSelector, + StreamingContext context, + ObjectManager? objectManager, + SerObjectInfoInit? serObjectInfoInit, + IFormatterConverter? converter, + bool bSimpleAssembly) { _objectType = objectType; _objectManager = objectManager; diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs index cb1d8f45cd6b4c..ae2f5423c27f23 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectReader.cs @@ -1,16 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Reflection; -using System.Diagnostics; -using System.Collections; namespace System.Runtime.Serialization.Formatters.Binary { internal sealed class ObjectReader { + private const string ObjectReaderUnreferencedCodeMessage = "ObjectReader requires unreferenced code"; + // System.Serializer information internal Stream _stream; internal ISurrogateSelector? _surrogates; @@ -74,6 +76,8 @@ internal ObjectReader(Stream stream, ISurrogateSelector? selector, StreamingCont _binder = binder; _formatterEnums = formatterEnums; } + + [RequiresUnreferencedCode("Types might be removed")] internal object Deserialize(BinaryParser serParser) { if (serParser == null) @@ -162,16 +166,21 @@ internal object CrossAppDomainArray(int index) return _crossAppDomainArray[index]; } - internal ReadObjectInfo CreateReadObjectInfo(Type objectType) + internal ReadObjectInfo CreateReadObjectInfo( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType) { return ReadObjectInfo.Create(objectType, _surrogates, _context, _objectManager, _serObjectInfoInit, _formatterConverter, _isSimpleAssembly); } - internal ReadObjectInfo CreateReadObjectInfo(Type? objectType, string[] memberNames, Type[]? memberTypes) + internal ReadObjectInfo CreateReadObjectInfo( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? objectType, + string[] memberNames, + Type[]? memberTypes) { return ReadObjectInfo.Create(objectType, memberNames, memberTypes, _surrogates, _context, _objectManager, _serObjectInfoInit, _formatterConverter, _isSimpleAssembly); } + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] internal void Parse(ParseRecord pr) { switch (pr._parseTypeEnum) @@ -218,6 +227,7 @@ private void ParseError(ParseRecord processing, ParseRecord onStack) private void ParseSerializedStreamHeaderEnd(ParseRecord pr) => _stack!.Pop(); // New object encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseObject(ParseRecord pr) { if (!_fullDeserialization) @@ -300,6 +310,7 @@ private void ParseObject(ParseRecord pr) } // End of object encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseObjectEnd(ParseRecord pr) { Debug.Assert(_stack != null); @@ -359,6 +370,7 @@ private void ParseObjectEnd(ParseRecord pr) } // Array object encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseArray(ParseRecord pr) { Debug.Assert(_stack != null); @@ -524,6 +536,7 @@ private void NextRectangleMap(ParseRecord pr) // Array object item encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseArrayMember(ParseRecord pr) { Debug.Assert(_stack != null); @@ -701,6 +714,7 @@ private void ParseArrayMember(ParseRecord pr) objectPr._memberIndex++; } + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseArrayMemberEnd(ParseRecord pr) { // If this is a nested array object, then pop the stack @@ -711,6 +725,7 @@ private void ParseArrayMemberEnd(ParseRecord pr) } // Object member encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseMember(ParseRecord pr) { Debug.Assert(_stack != null); @@ -825,6 +840,7 @@ private void ParseMember(ParseRecord pr) } // Object member end encountered in stream + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseMemberEnd(ParseRecord pr) { switch (pr._memberTypeEnum) @@ -846,6 +862,7 @@ private void ParseMemberEnd(ParseRecord pr) } // Processes a string object by getting an internal ID for it and registering it with the objectManager + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void ParseString(ParseRecord pr, ParseRecord parentPr) { // Process String class @@ -857,11 +874,13 @@ private void ParseString(ParseRecord pr, ParseRecord parentPr) } } + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void RegisterObject(object obj, ParseRecord pr, ParseRecord? objectPr) { RegisterObject(obj, pr, objectPr, false); } + [RequiresUnreferencedCode(ObjectReaderUnreferencedCodeMessage)] private void RegisterObject(object? obj, ParseRecord pr, ParseRecord? objectPr, bool bIsString) { if (!pr._isRegistered) @@ -937,6 +956,7 @@ internal long GetId(long objectId) return -1 * objectId; } + [RequiresUnreferencedCode("Types might be removed")] internal Type? Bind(string assemblyString, string typeString) { Type? type = null; @@ -957,6 +977,7 @@ internal sealed class TypeNAssembly public string? AssemblyName; } + [RequiresUnreferencedCode("Types might be removed")] internal Type? FastBindToType(string? assemblyName, string typeName) { Type? type = null; @@ -1046,6 +1067,7 @@ internal sealed class TypeNAssembly return null; } + [RequiresUnreferencedCode("Types might be removed")] private static void GetSimplyNamedTypeFromAssembly(Assembly assm, string typeName, ref Type? type) { // Catching any exceptions that could be thrown from a failure on assembly load @@ -1069,6 +1091,7 @@ private static void GetSimplyNamedTypeFromAssembly(Assembly assm, string typeNam private string? _previousName; private Type? _previousType; + [RequiresUnreferencedCode("Types might be removed")] internal Type? GetType(BinaryAssemblyInfo assemblyInfo, string name) { Type? objectType; @@ -1122,6 +1145,7 @@ public TopLevelAssemblyTypeResolver(Assembly topLevelAssembly) _topLevelAssembly = topLevelAssembly; } + [RequiresUnreferencedCode("Types might be removed")] public Type? ResolveType(Assembly? assembly, string simpleTypeName, bool ignoreCase) { if (assembly == null) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectWriter.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectWriter.cs index 7466fd9132760b..cf57a01929bb1b 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectWriter.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryObjectWriter.cs @@ -1,14 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization.Formatters.Binary { internal sealed class ObjectWriter { + private const string ObjectWriterUnreferencedCodeMessage = "ObjectWriter requires unreferenced code"; + private Queue? _objectQueue; private ObjectIDGenerator? _idGenerator; private int _currentId; @@ -47,6 +49,7 @@ internal ObjectWriter(ISurrogateSelector? selector, StreamingContext context, In _objectManager = new SerializationObjectManager(context); } + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] internal void Serialize(object graph, BinaryFormatterWriter serWriter) { if (graph == null) @@ -109,6 +112,7 @@ internal void Serialize(object graph, BinaryFormatterWriter serWriter) internal SerializationObjectManager ObjectManager => _objectManager; // Writes a given object to the stream. + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) { object? obj = objectInfo._obj; @@ -198,6 +202,7 @@ private void Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo } // Writes a given object to the stream. + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void Write(WriteObjectInfo objectInfo, NameInfo? memberNameInfo, NameInfo typeNameInfo, @@ -248,6 +253,7 @@ private void Write(WriteObjectInfo objectInfo, } } + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void WriteMemberSetup(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo, @@ -283,6 +289,7 @@ private void WriteMemberSetup(WriteObjectInfo objectInfo, } // Writes the members of an object + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void WriteMembers(NameInfo memberNameInfo, NameInfo memberTypeNameInfo, object? memberData, @@ -397,6 +404,7 @@ private void WriteMembers(NameInfo memberNameInfo, } // Writes out an array + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void WriteArray(WriteObjectInfo objectInfo, NameInfo? memberNameInfo, WriteObjectInfo? memberObjectInfo) { bool isAllocatedMemberNameInfo = false; @@ -569,6 +577,7 @@ private void WriteArray(WriteObjectInfo objectInfo, NameInfo? memberNameInfo, Wr } // Writes out an array element + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemTypeNameInfo, object? data) { arrayElemTypeNameInfo._isArrayItem = true; @@ -654,6 +663,7 @@ private void WriteArrayMember(WriteObjectInfo objectInfo, NameInfo arrayElemType } // Iterates over a Rectangle array, for each element of the array invokes WriteArrayMember + [RequiresUnreferencedCode(ObjectWriterUnreferencedCodeMessage)] private void WriteRectangle(WriteObjectInfo objectInfo, int rank, int[] maxA, Array array, NameInfo arrayElemNameTypeInfo, int[]? lowerBoundA) { int[] currentA = new int[rank]; diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryParser.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryParser.cs index 07ded6d66157ef..628d54d6118a21 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryParser.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryParser.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.InteropServices; @@ -11,6 +12,8 @@ namespace System.Runtime.Serialization.Formatters.Binary { internal sealed class BinaryParser { + private const string BinaryParserUnreferencedCodeMessage = "ObjectReader requires unreferenced code"; + private const int ChunkSize = 4096; private static readonly Encoding s_encoding = new UTF8Encoding(false, true); @@ -66,6 +69,7 @@ internal BinaryParser(Stream stream, ObjectReader objectReader) // Reads each record from the input stream. If the record is a primitive type (A number) // then it doesn't have a BinaryHeaderEnum byte. For this case the expected type // has been previously set to Primitive + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] internal void Run() { try @@ -303,6 +307,7 @@ internal void ReadAssembly(BinaryHeaderEnum binaryHeaderEnum) AssemIdToAssemblyTable[record._assemId] = new BinaryAssemblyInfo(record._assemblyString!); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadObject() { if (_binaryObject == null) @@ -373,6 +378,7 @@ private void ReadObject() _objectReader.Parse(pr); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] internal void ReadCrossAppDomainMap() { BinaryCrossAppDomainMap record = new BinaryCrossAppDomainMap(); @@ -395,6 +401,7 @@ internal void ReadCrossAppDomainMap() } } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] internal void ReadObjectWithMap(BinaryHeaderEnum binaryHeaderEnum) { if (_bowm == null) @@ -409,6 +416,7 @@ internal void ReadObjectWithMap(BinaryHeaderEnum binaryHeaderEnum) ReadObjectWithMap(_bowm); } + [RequiresUnreferencedCode("Types might be removed")] private void ReadObjectWithMap(BinaryObjectWithMap record) { BinaryAssemblyInfo? assemblyInfo = null; @@ -495,6 +503,7 @@ private void ReadObjectWithMap(BinaryObjectWithMap record) _objectReader.Parse(pr); } + [RequiresUnreferencedCode("Types might be removed")] internal void ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum) { if (_bowmt == null) @@ -509,6 +518,7 @@ internal void ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum) ReadObjectWithMapTyped(_bowmt); } + [RequiresUnreferencedCode("Types might be removed")] private void ReadObjectWithMapTyped(BinaryObjectWithMapTyped record) { BinaryAssemblyInfo? assemblyInfo = null; @@ -589,6 +599,7 @@ private void ReadObjectWithMapTyped(BinaryObjectWithMapTyped record) _objectReader.Parse(pr); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadObjectString(BinaryHeaderEnum binaryHeaderEnum) { if (_objectString == null) @@ -665,6 +676,7 @@ private void ReadObjectString(BinaryHeaderEnum binaryHeaderEnum) _objectReader.Parse(PRs); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadMemberPrimitiveTyped() { if (_memberPrimitiveTyped == null) @@ -712,6 +724,7 @@ private void ReadMemberPrimitiveTyped() _objectReader.Parse(PRs); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadArray(BinaryHeaderEnum binaryHeaderEnum) { BinaryAssemblyInfo? assemblyInfo = null; @@ -898,6 +911,7 @@ private void ReadArrayAsBytes(ParseRecord pr) } } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadMemberPrimitiveUnTyped() { ObjectProgress? objectOp = (ObjectProgress?)_stack.Peek(); @@ -930,6 +944,7 @@ private void ReadMemberPrimitiveUnTyped() _objectReader.Parse(PRs); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadMemberReference() { if (_memberReference == null) @@ -960,6 +975,7 @@ private void ReadMemberReference() _objectReader.Parse(PRs); } + [RequiresUnreferencedCode(BinaryParserUnreferencedCodeMessage)] private void ReadObjectNull(BinaryHeaderEnum binaryHeaderEnum) { if (_objectNull == null) diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryTypeConverter.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryTypeConverter.cs index 9dbe26f1fdd7e7..0ccb8f82e2df1b 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryTypeConverter.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/BinaryTypeConverter.cs @@ -1,8 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization.Formatters.Binary { @@ -191,6 +191,7 @@ internal static object ReadTypeInfo(BinaryTypeEnum binaryTypeEnum, BinaryParser } // Given the wire type information, returns the actual type and additional information + [RequiresUnreferencedCode("Types might be removed")] internal static void TypeFromInfo(BinaryTypeEnum binaryTypeEnum, object? typeInformation, ObjectReader objectReader, diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/ObjectMap.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/ObjectMap.cs index 1a3d907c92bf96..b3b924b12128e5 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/ObjectMap.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/Formatters/Binary/ObjectMap.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization.Formatters.Binary { @@ -22,7 +22,13 @@ internal sealed class ObjectMap internal int _objectId; internal BinaryAssemblyInfo _assemblyInfo; - internal ObjectMap(string objectName, Type objectType, string[] memberNames, ObjectReader objectReader, int objectId, BinaryAssemblyInfo assemblyInfo) + internal ObjectMap( + string objectName, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + string[] memberNames, + ObjectReader objectReader, + int objectId, + BinaryAssemblyInfo assemblyInfo) { _objectName = objectName; _objectType = objectType; @@ -45,6 +51,7 @@ internal ObjectMap(string objectName, Type objectType, string[] memberNames, Obj } } + [RequiresUnreferencedCode("Types might be removed")] internal ObjectMap(string objectName, string[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, object?[] typeInformationA, int[] memberAssemIds, ObjectReader objectReader, int objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable) { _objectName = objectName; @@ -99,11 +106,16 @@ internal ReadObjectInfo CreateObjectInfo(ref SerializationInfo? si, ref object?[ // No member type information internal static ObjectMap Create( - string name, Type objectType, string[] memberNames, ObjectReader objectReader, - int objectId, BinaryAssemblyInfo assemblyInfo) => + string name, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, + string[] memberNames, + ObjectReader objectReader, + int objectId, + BinaryAssemblyInfo assemblyInfo) => new ObjectMap(name, objectType, memberNames, objectReader, objectId, assemblyInfo); // Member type information + [RequiresUnreferencedCode("Types might be removed")] internal static ObjectMap Create( string name, string[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, object?[] typeInformationA, int[] memberAssemIds, ObjectReader objectReader, int objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable) => diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/IFormatter.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/IFormatter.cs index 2d3e412fbfacab..c1640a573bfbba 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/IFormatter.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/IFormatter.cs @@ -1,15 +1,20 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; namespace System.Runtime.Serialization { public interface IFormatter { + internal const string RequiresUnreferencedCodeMessage = "BinaryFormatter serialization is not trim compatible because the Type of objects being processed cannot be statically discovered."; + [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] object Deserialize(Stream serializationStream); [Obsolete(Obsoletions.BinaryFormatterMessage, DiagnosticId = Obsoletions.BinaryFormatterDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] + [RequiresUnreferencedCode(RequiresUnreferencedCodeMessage)] void Serialize(Stream serializationStream, object graph); ISurrogateSelector? SurrogateSelector { get; set; } SerializationBinder? Binder { get; set; } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/MemberHolder.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/MemberHolder.cs index c3006025db7091..2f46ebc96742e4 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/MemberHolder.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/MemberHolder.cs @@ -1,16 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; +using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization { internal sealed class MemberHolder { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] internal readonly Type _memberType; internal readonly StreamingContext _context; - internal MemberHolder(Type type, StreamingContext ctx) + internal MemberHolder( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type, + StreamingContext ctx) { _memberType = type; _context = ctx; diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs index c42125527494e8..d9eba9228f1fb0 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Reflection; -using System.Globalization; using System.Diagnostics.CodeAnalysis; +using System.Reflection; namespace System.Runtime.Serialization { @@ -15,6 +14,8 @@ public class ObjectManager private const int ArrayMask = MaxArraySize - 1; private const int MaxReferenceDepth = 100; + private const string ObjectManagerUnreferencedCodeMessage = "ObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered."; + private DeserializationEventHandler? _onDeserializationHandler; private SerializationEventHandler? _onDeserializedHandler; @@ -164,6 +165,7 @@ private bool GetCompletionInfo(FixupHolder fixup, [NotNullWhen(true)] out Object return true; } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] private void FixupSpecialObject(ObjectHolder holder) { ISurrogateSelector? uselessSelector = null; @@ -310,9 +312,11 @@ private bool DoValueTypeFixup(FieldInfo? memberToFix, ObjectHolder holder, objec { break; } - if (Nullable.GetUnderlyingType(parentField.FieldType) != null) + + FieldInfo? nullableValueField = GetNullableValueField(parentField.FieldType); + if (nullableValueField != null) { - fieldsTemp[currentFieldIndex] = parentField.FieldType.GetField(nameof(value), BindingFlags.NonPublic | BindingFlags.Instance)!; + fieldsTemp[currentFieldIndex] = nullableValueField; currentFieldIndex++; } @@ -379,6 +383,19 @@ private bool DoValueTypeFixup(FieldInfo? memberToFix, ObjectHolder holder, objec return true; } + [DynamicDependency("value", typeof(Nullable<>))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The Nullable.value field will be preserved by the DynamicDependency.")] + private static FieldInfo? GetNullableValueField(Type type) + { + if (Nullable.GetUnderlyingType(type) != null) + { + return type.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance)!; + } + + return null; + } + internal void CompleteObject(ObjectHolder holder, bool bObjectFullyComplete) { FixupHolderList? fixups = holder._missingElements; @@ -613,16 +630,19 @@ private void DoNewlyRegisteredObjectFixups(ObjectHolder holder) return holder.ObjectValue; } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public virtual void RegisterObject(object obj, long objectID) { RegisterObject(obj, objectID, null, 0, null); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public void RegisterObject(object obj, long objectID, SerializationInfo info) { RegisterObject(obj, objectID, info, 0, null); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public void RegisterObject(object obj, long objectID, SerializationInfo? info, long idOfContainingObj, MemberInfo? member) { RegisterObject(obj, objectID, info, idOfContainingObj, member, null); @@ -638,6 +658,7 @@ internal void RegisterString(string? obj, long objectID, SerializationInfo? info return; } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public void RegisterObject(object obj, long objectID, SerializationInfo? info, long idOfContainingObj, MemberInfo? member, int[]? arrayIndex) { if (obj == null) @@ -750,6 +771,7 @@ public void RegisterObject(object obj, long objectID, SerializationInfo? info, l /// The object to be completed. /// The SerializationInfo containing all info for obj. /// The streaming context in which the serialization is taking place. + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] internal void CompleteISerializableObject(object obj, SerializationInfo? info, StreamingContext context) { if (obj == null) @@ -775,7 +797,8 @@ internal void CompleteISerializableObject(object obj, SerializationInfo? info, S constInfo.Invoke(obj, new object?[] { info, context }); } - internal static ConstructorInfo GetDeserializationConstructor(Type t) + internal static ConstructorInfo GetDeserializationConstructor( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type t) { foreach (ConstructorInfo ci in t.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { @@ -791,6 +814,7 @@ internal static ConstructorInfo GetDeserializationConstructor(Type t) throw new SerializationException(SR.Format(SR.Serialization_ConstructorNotFound, t.FullName)); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public virtual void DoFixups() { ObjectHolder? temp; @@ -974,18 +998,21 @@ internal virtual void AddOnDeserialization(DeserializationEventHandler handler) _onDeserializationHandler = (DeserializationEventHandler)Delegate.Combine(_onDeserializationHandler, handler); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] internal virtual void AddOnDeserialized(object obj) { SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType()); _onDeserializedHandler = cache.AddOnDeserialized(obj, _onDeserializedHandler); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] internal virtual void RaiseOnDeserializedEvent(object obj) { SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType()); cache.InvokeOnDeserialized(obj, _context); } + [RequiresUnreferencedCode(ObjectManagerUnreferencedCodeMessage)] public void RaiseOnDeserializingEvent(object obj) { // Run the OnDeserializing methods diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs index 1bebb7b5192081..9e8d8d38f30b6c 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationEventsCache.cs @@ -4,6 +4,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace System.Runtime.Serialization @@ -15,7 +16,7 @@ internal sealed class SerializationEvents private readonly List? _onDeserializingMethods; private readonly List? _onDeserializedMethods; - internal SerializationEvents(Type? t) + internal SerializationEvents([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? t) { _onSerializingMethods = GetMethodsWithAttribute(typeof(OnSerializingAttribute), t); _onSerializedMethods = GetMethodsWithAttribute(typeof(OnSerializedAttribute), t); @@ -23,7 +24,10 @@ internal SerializationEvents(Type? t) _onDeserializedMethods = GetMethodsWithAttribute(typeof(OnDeserializedAttribute), t); } - private List? GetMethodsWithAttribute(Type attribute, Type? t) + private List? GetMethodsWithAttribute( + Type attribute, + // currently the only way to preserve base, non-public methods is to use All + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? t) { List? mi = null; @@ -93,7 +97,12 @@ internal static class SerializationEventsCache { private static readonly ConcurrentDictionary s_cache = new ConcurrentDictionary(); - internal static SerializationEvents GetSerializationEventsForType(Type t) => - s_cache.GetOrAdd(t, type => new SerializationEvents(type)); + internal static SerializationEvents GetSerializationEventsForType( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type t) => + s_cache.GetOrAdd(t, type => CreateSerializationEvents(type)); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:UnrecognizedReflectionPattern", + Justification = "The Type is annotated correctly, it just can't pass through the lambda method.")] + private static SerializationEvents CreateSerializationEvents(Type t) => new SerializationEvents(t); } } diff --git a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationObjectManager.cs b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationObjectManager.cs index 9e194d4b2cdb49..69ae9935da416e 100644 --- a/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationObjectManager.cs +++ b/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationObjectManager.cs @@ -2,11 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization { public sealed class SerializationObjectManager { + private const string SerializationObjectManagerUnreferencedCodeMessage = "SerializationObjectManager is not trim compatible because the Type of objects being managed cannot be statically discovered."; + private readonly Dictionary _objectSeenTable; // Table to keep track of objects [OnSerializing] has been called on private readonly StreamingContext _context; private SerializationEventHandler? _onSerializedHandler; @@ -17,6 +20,7 @@ public SerializationObjectManager(StreamingContext context) _objectSeenTable = new Dictionary(); } + [RequiresUnreferencedCode(SerializationObjectManagerUnreferencedCodeMessage)] public void RegisterObject(object obj) { // Invoke OnSerializing for this object @@ -38,6 +42,7 @@ public void RegisterObject(object obj) public void RaiseOnSerializedEvent() => _onSerializedHandler?.Invoke(_context); + [RequiresUnreferencedCode(SerializationObjectManagerUnreferencedCodeMessage)] private void AddOnSerialized(object obj) { SerializationEvents cache = SerializationEventsCache.GetSerializationEventsForType(obj.GetType());