静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载导读本文围绕 CodeQL C# 提取器在 2020 年 8 月的一次重要行为变更展开此前 C# 源码中的分部方法体partial method body在提取阶段会被跳过从该变更起被完整提取。通过阅读本文你将理解 CodeQL 如何从 Roslyn 编译模型中识别分部声明、如何将方法/属性/事件的分部实现部分与定义部分关联起来以及这一能力对数据流分析与跨文件查询的实战意义。变更背景为什么分部方法体此前会被跳过在 C# 语言中partial修饰符允许将一个类、结构体或方法的声明拆分到多个源文件甚至多个编译单元中。其中「分部方法」是一种特殊的成员声明它由**定义部分declaring/defining part与实现部分implementing part**组成典型形态如下// 定义部分只声明签名不带方法体或带抽象实现 partial void OnSaving(Customer customer); // 实现部分在另一个文件中提供实际方法体 partial void OnSaving(Customer customer) { // 业务逻辑 }在 C# 语义中若分部方法只有定义部分而没有实现部分编译器会自动丢弃对该方法的调用反之实现部分才是真正会执行代码的位置。因此对于静态分析而言实现部分的方法体是数据流、污点分析和可达性分析的核心素材——如果提取器跳过它将导致控制流图CFG缺失真实执行路径污点分析无法追踪通过分部方法传递的敏感数据基于调用关系的查询如跨程序分析产生漏报。本次变更csharp/old-change-notes/2020-08-18-partial-method-bodies.md标签lgtm,codescanning正是为了修复这一漏提取问题使提取器对partial声明采用与其他普通成员一致的处理路径。提取器的底层实现通过 Roslyn 关联定义与实现部分CodeQL 的 C# 提取器基于 Roslyn.NET 编译器平台的符号模型工作。分部方法、分部属性和分部事件在 Roslyn 符号层面会被表示为两个分离的符号定义部分与实现部分。若提取器只处理其中一个符号就会丢失方法体或重复创建实体。仓库中的关键工具方法位于 csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs它提供了统一的「取实现部分」逻辑public static IMethodSymbol GetBodyDeclaringSymbol(this IMethodSymbol method) method.PartialImplementationPart ?? method; public static IPropertySymbol GetBodyDeclaringSymbol(this IPropertySymbol property) property.PartialImplementationPart ?? property; public static IEventSymbol GetBodyDeclaringSymbol(this IEventSymbol symbol) symbol.PartialImplementationPart ?? symbol;三个扩展方法遵循同一模式若符号存在PartialImplementationPart即它是某个分部声明的定义部分则返回实现部分作为方法体归属者否则返回符号自身。这样提取器在生成 TRAP 实体时总能定位到真正携带方法体的那一端从而保证方法体body被正确提取而非跳过定义部分与实现部分被折叠为同一逻辑实体避免重复提取属性与事件的访问器accessor同样能拿到实现端保证get/set/add/remove访问器的方法体不被遗漏。与之配套的守卫逻辑出现在访问器实体中csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs 与 csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs 中均有!Symbol.IsPartialDefinition; // Accessors always have an implementing declaration as well.即访问器符号若处于「仅定义、无实现」的 partial 状态则不应被当作独立实体提取——因为访问器总是伴随实现声明存在此时应交给实现部分处理。这正是「分部方法体被跳过」问题在符号层面的根因与修复点此前提取器可能把纯定义部分当作完整方法处理导致方法体位置为空修复后通过PartialImplementationPart显式归一化到实现端。QL 库侧分部成员如何暴露给查询作者提取完成后QL 侧需要把「是否分部」这一事实暴露给查询作者。CodeQL C# 库在 csharp/ql/lib/semmle/code/csharp/Member.qll 中为所有可带修饰符的声明统一提供了/** Holds if this declaration is partial. */ predicate isPartial() { this.hasModifier(partial) }该谓词位于Modifiable类中因此方法、属性、事件、类、结构体等一切可声明partial的实体都能直接调用isPartial()。需要注意的是isPartial()判定的是源码中是否出现partial修饰符与语言语法一致而提取器内部对定义/实现部分的归一化是另一层机制——二者配合使查询作者既能识别「这是分部声明」又能获得「完整方法体已被提取」的保证。此外QL 库中多处针对「多源码位置」的分部声明做了防御性处理例如csharp/ql/lib/semmle/code/csharp/PrintAst.qll 注明一个Element如namespace和partial class可能拥有多个位置打印 AST 时必须聚合处理csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll 注明partial方法可能具有多个源码位置分发逻辑需兼容该情形。这些注释与isPartial()共同说明分部声明在 CodeQL C# 模型中是一等公民跨文件位置是建模与查询都要考虑的因素。测试佐证分部类在真实查询中的行为仓库的查询测试中也有分部声明的直接用例。在 csharp/ql/test/query-tests/standalone/Bad Practices/Control-Flow/ConstantCondition/ConstantCondition.cs 中partial class C1 { public C2 Prop { get; set; } }该文件配合同目录下的 ConstantCondition.expected 与 ConstantCondition.qlref 一起构成恒真/恒假条件检测查询的回归测试。它验证了即便成员声明位于partial class中其属性类型与访问器的提取结果依然准确查询不会因分部声明而产生误报或漏报。这从测试侧印证了「分部声明与其他成员采用一致的提取与建模路径」。实战影响与建议对查询作者判断一个方法是否分部请使用method.isPartial()Method继承自Modifiable判断类是否分部同理使用type.isPartial()。由于提取器已将定义/实现部分归一化查询中通过Callable.getBody()或Method.getBody()获取方法体时分部方法总能拿到实现端的真实方法体无需自行拼接跨文件位置。若你关心声明跨了多少个文件可结合位置的聚合逻辑参见 PrintAst.qll 的注释自行统计CodeQL 的Element模型本身允许一个实体对应多个位置。对数据流与污点分析分部方法常出现在实体框架、序列化器及代码生成场景如源生成器生成的partial实现这些场景恰恰是污点传播的高发地带。本次修复保证数据流路径可以穿过分部方法体而不是在定义部分处断裂参见 DataFlowDispatch.qll 对 partial 方法的专门处理由编译器/生成器产出的实现端代码与手写定义端代码被统一建模跨程序分析结果更完整。版本与适用前提本变更属于 CodeQL C# 提取器的行为改进随仓库的lgtm/codescanning发布渠道生效见变更记录文件的标签行。若你的分析结果中分部方法方法体缺失请确认所使用的 CodeQL 工具链已包含本变更之后的提取器版本。小结变更点C# 分部方法体从「被跳过」变为「被完整提取」见 2020-08-18-partial-method-bodies.md。实现原理提取器通过 Roslyn 的PartialImplementationPart将定义部分归一化到实现部分SymbolExtensions.cs访问器实体对IsPartialDefinition做守卫Accessor.cs。查询接口QL 库为所有可修饰声明提供isPartial()Member.qll。测试保障恒真/恒假条件检测测试覆盖了partial class场景ConstantCondition.cs。分部声明在真实 C# 工程中极为常见本变更消除了数据流分析在分部方法边界处的盲区是 CodeQL C# 模型向「完整可分析」迈进的关键一环。赞分享静态分析SAST应用安全漏洞扫描代码质量【免费下载链接】codeqlCodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security项目地址https://gitcode.com/gh_mirrors/co/codeql点击查看免费下载相关推荐CodeQL C 提取器对预处理器指令的支持从 if 到 line 的完整建模CodeQL C 提取器对预处理器指令的支持从 if 到 line 的完整建模 导读 本篇文章围绕 CodeQL 仓库中 C 语言库对预处理器指令Prepr静态分析SAST应用安全漏洞扫描代码质量CodeQL C 提取器对函数指针的支持FunctionPointerType 与 FunctionPointerCall 的实现与查询实战CodeQL C 提取器对函数指针的支持 FunctionPointerType 与 FunctionPointerCall 的实现与查询实战 导读 C 9.静态分析SAST应用安全漏洞扫描代码质量深入解析 CodeQL C 对 DoesNotReturnIfAttribute 断言方法的支持与精度提升深入解析 CodeQL C 对 DoesNotReturnIfAttribute 断言方法的支持与精度提升 导读 本文基于 CodeQL 仓库 C 分析器的官方静态分析SAST应用安全漏洞扫描代码质量上一篇符号链接 Monorepo 中 TypeScript 自动导入的增量缓存autoImportSymlinkedMonorepoSourceUpdate 基线全解析下一篇SRWE窗口编辑免费搞定游戏超清截图创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考