“Microsoft 最少量建议规则”代码分析规则集
可以使用“Microsoft 最少量建议规则”规则集重点解决代码中最关键的问题,包括潜在的安全漏洞、应用程序崩溃和其他重要的逻辑和设计错误。 在为项目创建的任何自定义规则集中都应加入此规则集。
规则 |
说明 |
---|---|
一个类声明并实现 System.IDisposable 类型的实例字段,但该类不实现 IDisposable。 声明 IDisposable 字段的类间接拥有非托管资源,并且应该实现 IDisposable 接口。 |
|
事件处理程序方法采用两个参数。 第一个参数属于 System.Object 类型,名为“sender”。 它是引发事件的对象。 第二个参数属于 System.EventArgs 类型,名为“e”。 该参数是与事件关联的数据。 事件处理程序方法不应返回值;在 C# 编程语言中,这由返回类型 void 指示。 |
|
.NET Framework 使用版本号唯一地标识程序集,并绑定到具有强名称的程序集中的类型。 版本号与版本和发行者策略一起使用。 默认情况下,仅使用用于生成应用程序的程序集版本运行应用程序。 |
|
未密封的外部可见类型提供了显式实现公共接口的方法,但没有提供具有相同名称的其他外部可见方法。 |
|
分配非托管资源的类型应该实现 IDisposable,以使调用方可以根据需要释放这些资源,并缩短持有这些资源的对象的生存期。 |
|
平台调用方法(例如标以 System.Runtime.InteropServices.DllImportAttribute 特性的那些方法,或在 Visual Basic 中使用 Declare 关键字定义的方法)可以访问非托管代码。 这些方法应属于 NativeMethods、SafeNativeMethods 或 UnsafeNativeMethods 类。 |
|
如果派生方法的参数签名只是在类型方面有所不同,而且与基方法的参数签名中的对应类型相比,这些类型的派生方式更弱,则基类型中的方法将被派生类型中的同名方法隐藏。 |
|
所有的 IDisposable 类型都应当正确实现 Dispose 模式。 |
|
不应引发异常的方法引发了异常。 |
|
访问键也称为快捷键,它通过使用 Alt 键来实现对控件的键盘访问。 如果多个控件具有重复的访问键,则访问键的行为定义不正确。 |
|
公共或受保护方法标有 System.Runtime.InteropServices.DllImportAttribute 特性。 未能找到非托管库,或者未能将方法与库中的函数匹配。 |
|
公共类型中的公共或受保护方法具有 System.Runtime.InteropServices.DllImportAttribute 特性(还在 Visual Basic 中由 Declare 关键字实现)。 这些方法不能公开。 |
|
某个 COM 可见的值类型标有设置为 LayoutKind.Auto 的 System.Runtime.InteropServices.StructLayoutAttribute 特性。 这些类型的布局因 .NET Framework 的版本不同而不同,这将中断要求特定布局的 COM 客户端。 |
|
调用了 Marshal.GetLastWin32Error 方法或等效的 Win32 GetLastError 函数,并且紧邻的前一个调用并非针对平台调用方法。 |
|
某个 COM 可见的类型是从非 COM 可见的类型派生而来。 |
|
某个类型声明了标以 System.Runtime.InteropServices.ComRegisterFunctionAttribute 特性的方法,但没有声明标以 System.Runtime.InteropServices.ComUnregisterFunctionAttribute 特性的方法,或相反。 |
|
此规则查找针对 Win32 函数的平台调用方法声明,这些函数具有指向 OVERLAPPED 结构参数的指针,而对应的托管参数不是指向 System.Threading.NativeOverlapped 结构的指针。 |
|
此规则对以下项进行检查:当用显式布局声明的结构封送到 64 位操作系统上的非托管代码时,是否正确对齐。 |
|
此规则计算 P/Invoke 的每个参数和返回值的大小,还验证它们在封送到 32 位和 64 位操作系统上的非托管代码时的大小是否正确。 |
|
由于可能发生异常事件,导致对象的终结器无法运行,因此,应显式释放对象,以避免对该对象的所有引用超出范围。 |
|
当可以跨应用程序域边界直接进行访问对象时,则认为该对象具有弱标识。 对于尝试获取对具有弱标识的对象的锁的线程,该线程可能会被其他应用程序域中持有对同一对象的锁的另一线程所阻止。 |
|
一个方法使用按该方法的字符串参数生成的字符串设置 System.Data.IDbCommand.CommandText 属性。 此规则假定字符串参数中包含用户输入。 基于用户输入生成的 SQL 命令字符串易于受到 SQL 注入式攻击。 |
|
某平台调用成员允许部分受信任的调用方,具有一个字符串参数,并且不显式封送该字符串。 这可能导致潜在的安全漏洞。 |
|
公共或受保护值类型受数据访问或链接要求保护。 |
|
指针不是私有、内部或只读指针。 恶意代码可以更改指针的值,这样就有可能访问内存中的任意位置或导致应用程序或系统故障。 |
|
一个公共或受保护类型包含公共字段,并受链接要求保护。 如果代码可以访问受链接要求保护的类型的实例,则该代码不必满足此链接要求就可以访问该类型的字段。 |
|
一个方法不应同时有同一操作的方法级别和类型级别的声明性安全。 |
|
在完全受信任的程序集具有 APTCA (AllowPartiallyTrustedCallers) 特性时,如果该程序集执行另一个不允许部分受信任调用方的程序集中的代码,则可能存在安全漏洞。 |
|
在完全受信任的程序集具有 APTCA (AllowPartiallyTrustedCallers) 特性时,如果程序集中的某个类型是从不允许部分受信任调用方的类型继承而来,则可能会产生安全漏洞。 |
|
公共或受保护成员具有链接要求,且由不执行任何安全检查的成员调用。 链接请求仅检查直接调用方的权限。 |
|
该规则将一个方法与其基方法(该基方法为另一个类型中的接口或虚方法)相匹配,然后比较两者的链接请求。 如果与此规则冲突,则恶意调用方只需调用不安全的方法,即可跳过该链接要求。 |
|
公共或受保护方法中含有 try/finally 块。 finally 块似乎要重置安全状态,并且自身不包括在某个 finally 块中。 |
|
一个公共的非密封类型受链接要求保护,并且具有可重写的方法。 类型和方法都不受继承要求保护。 |
|
某个类型参与了类型等效,该类型本身或该类型的成员或字段用 SecurityCriticalAttribute 特性标记。 对于任何关键的类型或包含参与类型等效的关键方法或字段的类型,将引发此规则。 当 CLR 检测到这样的类型时,在运行时将不会加载它并引发 TypeLoadException。 通常,仅在用户手动实现类型等效而不是通过依赖 tlbimp 和编译器进行类型等效时,才会引发此规则。 |
|
具有 SecurityCriticalAttribute 的类型和成员无法供 Silverlight 应用程序代码使用。 安全关键类型和成员只能供 .NET Framework for Silverlight 类库中的受信任代码使用。 因为派生类中的某个公共或受保护构造必须有与其基类相同或更大的透明度,所以不能从标记为 SecurityCritical 类中派生应用程序中的类。 |
|
将对一个具有以下特点的方法引发此警告:该方法将用 SecurityCriticalAttribute 标记的委托绑定到一个透明的或用 SecuritySafeCriticalAttribute 标记的方法。 还会对另一个具有以下特点的方法引发此警告:该方法将透明的或安全关键的委托绑定到一个关键方法。 |
|
当用 SecurityCriticalAttribute 标记的方法重写一个透明的或用 SecuritySafeCriticalAttribute 标记的方法时,将会引发此规则。 当一个透明的或用 SecuritySafeCriticalAttribute 标记的方法重写一个用 SecurityCriticalAttribute 标记的方法时,也会引发此规则。 该规则在重写虚方法或实现接口时应用。 |
|
某个方法包含无法验证的代码或通过引用返回类型。 在尝试通过安全透明代码执行无法验证的 Microsoft 中间语言 (MSIL) 时将引发此规则。 但是,此规则不包含完整的 IL 验证程序,而是使用试探法来捕捉 MSIL 验证的大部分冲突。 |
|
一个安全透明方法调用使用 SuppressUnmanagedCodeSecurityAttribute 特性标记的方法。 |
|
安全透明方法调用未用 APTCA 特性标记的程序集中的方法,或者安全透明方法满足某个类型或方法的 LinkDemand。 |
|
安全透明方法调用未用 APTCA 特性标记的程序集中的方法,或者安全透明方法满足某个类型或方法的 LinkDemand。 |
|
标记为 SecurityTransparentAttribute 的代码未被授予足够的权限进行断言。 |
|
对于直接调用到本机代码中(例如通过使用 P/Invoke)的任何透明方法,将引发此规则。 违反此规则会导致级别 2 透明度模型中的 MethodAccessException,以及级别 1 透明度模型中对 UnmanagedCode 的完全要求。 |
|
异常被再次引发,在 throw 语句中显式指定了该异常。 如果通过在 throw 语句中指定异常来重新引发该异常,则引发该异常的原始方法与当前方法之间的方法调用的列表将丢失。 |
|
某个方法实现所包含的代码路径可能导致对同一对象多次调用 System.IDisposable.Dispose 或与 Dispose 等效的方法(例如,用于某些类型的 Close() 方法)。 |
|
某值类型声明了显式静态构造函数。 要修复与该规则的冲突,请在声明它时初始化所有静态数据并移除静态构造函数。 |
|
继承自 System.EnterpriseServices.ServicedComponent 的类型中的方法标记有 System.Web.Services.WebMethodAttribute。 因为 WebMethodAttribute 和 ServicedComponent 方法在上下文和事务流方面的行为和要求有冲突,所以该方法的行为在某些情况下会不正确。 |
|
实现 System.IDisposable 的类型声明了同样实现 IDisposable 的类型的字段。 字段的 Dispose 方法不由声明类型的 Dispose 方法调用。 |
|
构造函数调用虚方法时,可能尚未执行调用该方法的实例的构造函数。 |
|
实现 System.IDisposable 并包含建议使用非托管资源的字段的类型未实现 Object.Finalize 所描述的终结器。 |
|
终止必须通过继承层次结构传播。 为确保这一点,类型必须从其自身的 Finalize 方法调用它们的基类 Finalize 方法。 |
|
要修复与该规则的冲突,请实现序列化构造函数。 对于密封类,请使构造函数成为私有;否则,请使构造函数成为受保护。 |
|
STAThreadAttribute 指示应用程序的 COM 线程模型是单线程单元。 使用 Windows 窗体的任何应用程序的入口点上必须存在此特性;如果没有此特性,则 Windows 组件可能无法正常工作。 |
|
在可以序列化的类型中声明了类型不可序列化的实例字段。 |
|
若要修复与该规则的冲突,请从相应的派生类型方法或构造函数调用基类型 GetObjectData 方法或序列化构造函数。 |
|
若要被公共语言运行时识别为可序列化,类型必须用 SerializableAttribute 特性标记,即使该类型通过实现 ISerializable 接口使用了自定义的序列化例程也是如此。 |
|
处理序列化事件的方法的签名、返回类型或可见性不正确。 |
|
若要修复与该规则的冲突,请使 GetObjectData 方法可见且可以重写,并确保所有实例字段都包括在序列化进程中,或者使用 NonSerializedAttribute 特性显式标记所有实例字段。 |
|
传递给 System.String.Format 的 format 参数不包含对应于每个对象参数的格式项,反之亦然。 |
|
此表达式对照 Single.Nan 或 Double.Nan 测试某个值。 使用 Single.IsNan(Single) 或 Double.IsNan(Double) 测试该值。 |