Skip to content

Commit

Permalink
Remove support for binary serialization reflection analysis
Browse files Browse the repository at this point in the history
IL Linker is also removing this support in dotnet/linker#1925.

We could keep the reflection blocking exemption, but there's a workaround: just turn off reflection blocking.
  • Loading branch information
MichalStrehovsky committed Mar 28, 2021
1 parent 59277cf commit 28620ac
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,12 @@ private bool ComputeIsBlocked(EcmaType type, ModuleBlockingMode blockingMode)

DefType containingType = type.ContainingType;
var typeDefinition = type.MetadataReader.GetTypeDefinition(type.Handle);

// [Serializable] types may be serialized by reflection-based serializers, so we need to
// permit limited reflection over them. Details are at https://msdn.microsoft.com/en-us/library/system.serializableattribute(v=vs.110).aspx
bool blockIfNotVisibleOrAccessible = true;
if (type.IsSerializable)
{
blockIfNotVisibleOrAccessible = false;
}

if (containingType == null)
{
if ((typeDefinition.Attributes & TypeAttributes.Public) == 0)
{
return blockIfNotVisibleOrAccessible;
return true;
}
}
else
Expand All @@ -144,7 +136,7 @@ private bool ComputeIsBlocked(EcmaType type, ModuleBlockingMode blockingMode)
}
else
{
return blockIfNotVisibleOrAccessible || ComputeIsBlocked((EcmaType)containingType, blockingMode);
return true;
}
}

Expand All @@ -154,17 +146,13 @@ private bool ComputeIsBlocked(EcmaType type, ModuleBlockingMode blockingMode)
private BlockedTypeHashtable _blockedTypes;

private MetadataType ArrayOfTType { get; }
private MetadataType SerializationInfoType { get; }
private MetadataType ISerializableType { get; }
private MetadataType AttributeType { get; }

public BlockedInternalsBlockingPolicy(TypeSystemContext context)
{
_blockedTypes = new BlockedTypeHashtable(_blockedModules);

ArrayOfTType = context.SystemModule.GetType("System", "Array`1", false);
SerializationInfoType = context.SystemModule.GetType("System.Runtime.Serialization", "SerializationInfo", false);
ISerializableType = context.SystemModule.GetType("System.Runtime.Serialization", "ISerializable", false);
AttributeType = context.SystemModule.GetType("System", "Attribute", false);
}

Expand Down Expand Up @@ -205,31 +193,6 @@ public override bool IsBlocked(MethodDesc method)
&& accessibility != MethodAttributes.FamORAssem
&& accessibility != MethodAttributes.Public)
{
// Non-public and non-protected methods should be blocked, but binary serialization
// forces us to exclude a couple things if the type is serializable.
if (owningType.IsSerializable)
{
MethodSignature signature = ecmaMethod.Signature;

if (ecmaMethod.IsConstructor
&& signature.Length == 2
&& signature[0] == SerializationInfoType
/* && ecmaMethod.Signature[1] is StreamingContext */)
{
return false;
}

// Methods with these attributes can be called during serialization
if (signature.Length == 1 && !signature.IsStatic && signature.ReturnType.IsVoid &&
(ecmaMethod.HasCustomAttribute("System.Runtime.Serialization", "OnSerializingAttribute")
|| ecmaMethod.HasCustomAttribute("System.Runtime.Serialization", "OnSerializedAttribute")
|| ecmaMethod.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializingAttribute")
|| ecmaMethod.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializedAttribute")))
{
return false;
}
}

return true;
}

Expand Down Expand Up @@ -270,17 +233,6 @@ public override bool IsBlocked(FieldDesc field)
&& accessibility != FieldAttributes.FamORAssem
&& accessibility != FieldAttributes.Public)
{
// Non-public and non-protected fields should be blocked, but binary serialization
// forces us to exclude some fields if the type is serializable.
if (owningType.IsSerializable
&& !ecmaField.IsStatic
&& !ecmaField.IsNotSerialized
&& ISerializableType != null
&& !owningType.CanCastTo(ISerializableType))
{
return false;
}

// Exempt fields on custom attributes from blocking.
// Attribute.Equals and Attribute.GetHashCode depends on being able to
// walk all fields on custom attributes using reflection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ public sealed class UsageBasedMetadataManager : GeneratingMetadataManager

private readonly HashSet<string> _rootEntireAssembliesModules;

private readonly MetadataType _serializationInfoType;

internal FlowAnnotations FlowAnnotations { get; }

internal Logger Logger { get; }
Expand All @@ -76,8 +74,6 @@ public UsageBasedMetadataManager(
_compilationModuleGroup = group;
_generationOptions = generationOptions;

_serializationInfoType = typeSystemContext.SystemModule.GetType("System.Runtime.Serialization", "SerializationInfo", false);

FlowAnnotations = flowAnnotations;
Logger = logger;

Expand Down Expand Up @@ -244,35 +240,6 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc
}
}

// If a type is marked [Serializable], make sure a couple things are also included.
if (type.IsSerializable && !type.IsGenericDefinition)
{
foreach (MethodDesc method in type.GetAllMethods())
{
MethodSignature signature = method.Signature;

if (method.IsConstructor
&& signature.Length == 2
&& signature[0] == _serializationInfoType
/* && signature[1] is StreamingContext */)
{
dependencies = dependencies ?? new DependencyList();
dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization");
}

// Methods with these attributes can be called during serialization
if (signature.Length == 1 && !signature.IsStatic && signature.ReturnType.IsVoid &&
(method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializingAttribute")
|| method.HasCustomAttribute("System.Runtime.Serialization", "OnSerializedAttribute")
|| method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializingAttribute")
|| method.HasCustomAttribute("System.Runtime.Serialization", "OnDeserializedAttribute")))
{
dependencies = dependencies ?? new DependencyList();
dependencies.Add(factory.CanonicalEntrypoint(method), "Binary serialization");
}
}
}

// Event sources need their special nested types
if (mdType != null && mdType.HasCustomAttribute("System.Diagnostics.Tracing", "EventSourceAttribute"))
{
Expand Down

0 comments on commit 28620ac

Please sign in to comment.