.Net二进制反序列化运行时平台的故障检测/取证

cbc*_*lin 12 .net serialization instrumentation

我正在寻找有关如何检测运行时平台以揭示Microsoft .Net二进制反序列化失败的源类型的见解.

When using BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine) and one of the types does not exist in the current binaries; instead of throwing an error, .Net inserts the object [TypeLoadExceptionHolder]. Particularly for collections, this causes no immediate problem.

Subsequently when the collection is serialized for transmission between application tiers; the platform receives a 'serialization failure' because [TypeLoadExceptionHolder] cannot be serialized. So the resulting error is useless for actually providing clues as to the source-type that caused the problem. Now the hunt (time suck) is on to see which developer (of hundreds) added a new type to a million-line platform.

由于用于支持平台会话缓存的序列化流,因此某些频率会出现此问题.代码经常以增量方式部署.客户页面请求可以在部署窗口期间在代码库的旧版本和新版本之间跳转.粗心地引入新类型会导致旧版本的页面请求爆炸.

任何有关提供运行时丰富的错误/陷阱的想法将不胜感激.


(SerializationException) 
Type 'System.Runtime.Serialization.TypeLoadExceptionHolder' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable. 
- at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) 
- at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) 
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) 
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) 
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) 
- at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) 
Run Code Online (Sandbox Code Playgroud)

Mic*_*ito 5

好吧,您可以采取的一种方法是使用自定义在反序列化期间SerializationBinder覆盖BindToType和检查类型名称。

根据您想要完成的任务,当您确定未知类型时,您可以:

  • 引发异常(悲观):尽早发现问题,并可以使用自定义消息或异常轻松识别类型。

  • 记录类型名称(乐观):如果存在未知类型正常的情况,日志记录将提供诊断异常所需的详细信息,如果它们稍后在序列化期间发生。

您还可以根据类型名称的特征选择不同的方法(即,如果类型似乎是您的应用程序的一部分或第三方库的一部分)。

TypeLoadExceptionHolder在反序列化期间创建的实例确实包含一个非公共成员TypeName,该成员包含无法解析的类型的名称。但是,该实例在SerializationException您稍后遇到的情况下不可用,即使如此,该值也只能通过可信上下文中的反射获得。

public class CustomSerializationBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        Type t = Type.GetType(string.Concat(typeName, ", ", assemblyName));

        if (t == null)
        {
            throw new SerializationException(string.Format("Type {0} from assembly {1} could not be bound.", typeName, assemblyName));
        }

        return t;
    }

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        base.BindToName(serializedType, out assemblyName, out typeName);
    }
}

...

BinaryFormatter.Binder = new CustomSerializationBinder();
Run Code Online (Sandbox Code Playgroud)