首页 / 资讯中心 / 文章详情

CodeQL C 库对 C 9 unary `not` 模式的完整支持:UnaryPatternExpr 与 NotPatternExpr 解析

CodeQL C 库对 C 9 unary `not` 模式的完整支持:UnaryPatternExpr 与 NotPatternExpr 解析 ★ FEATURED ARTICLE
静态分析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点击查看免费下载本文基于 csharp/old-change-notes/2021-01-14-Unary-pattern.md 这一变更说明展开。它记录了 CodeQL 的 C# 分析库为支持 C# 9 一元not模式unary not pattern而新增的UnaryPatternExpr与NotPatternExpr两个 QL 类。读者读完本文后将能够理解这两个 QL 类在类层次中的位置与 API掌握not模式从 Roslyn 语法树经提取器落入 TRAP 的完整链路并了解守卫分析guards如何利用NotPatternExpr推导null匹配与相等性测试的极性从而在数据流与污点分析中获得更精确的路径条件。变更说明原文与适用范围原文档 2021-01-14-Unary-pattern.md 全文如下lgtm,codescanning * The UnaryPatternExpr and NotPatternExpr classes have been added to support C# 9 unary not pattern.其中lgtm,codescanning是该变更说明的适用标签labels表示这项库变更同时纳入 LGTM 与 GitHub code scanning 两个产品的查询集发布核心内容是为支持 C# 9 的一元not模式在 QL 库中新增了UnaryPatternExpr与NotPatternExpr两个类。C# 9 的模式匹配语法pattern matching引入了几种组合模式combinator patterns其中一元not模式形如not pattern用于否定一个子模式例如x is not null、c is not a、i is not 1。此后CodeQL 的 C# 分析库可以在is表达式、switch表达式与switch语句中识别并分析这类模式从而正确建模其布尔语义。QL 类层次UnaryPatternExpr 与 NotPatternExpr 的定义两个新类都定义在 csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll 中位于模式表达式pattern expression家族内/** A unary pattern. For example, not 1. */ class UnaryPatternExpr extends PatternExpr, unary_pattern_expr { /** Gets the underlying pattern. */ PatternExpr getPattern() { result this.getChild(0) } } /** A not pattern. For example, not 1. */ class NotPatternExpr extends UnaryPatternExpr, not_pattern_expr { override string toString() { result not ... } override string getAPrimaryQlClass() { result NotPatternExpr } }要点UnaryPatternExpr继承自PatternExpr并关联数据库实体unary_pattern_expr。它只有一个核心 APIgetPattern()返回not关键字后的一元子模式即this.getChild(0)例如not 1中的常量模式1NotPatternExpr继承UnaryPatternExpr关联not_pattern_expr重写了toString()输出为not ...与getAPrimaryQlClass()。它是一元模式在当前库中的具体化——当前 C# 语法中的一元模式即not模式因此NotPatternExpr是UnaryPatternExpr唯一的直接子类从 Expr.qll 的getAChildExpr()实现可以看到unary_pattern_expr被纳入模式子表达式的遍历逻辑exists(Expr mid | hasChildPattern(pm, mid) and mid instanceof unary_pattern_expr | child mid.getChildExpr(0))。这意味着在 AST 遍历中not模式内部嵌套的子模式如常量模式、递归模式会被正确枚举供各类查询访问。在Expr.qll的同一段代码中还可以看到与之相邻的组合模式类BinaryPatternExpr/OrPatternExpr/AndPatternExpr如1 or 2、 1 and 2、ListPatternExpr、SlicePatternExpr等它们共同构成 C# 9 模式语法的 QL 镜像。提取器从 RoslynUnaryPatternSyntax到 TRAP 实体QL 类只是数据库上的视图真正将源码中的not模式写入 TRAP 数据库的是 C# 提取器。提取器使用 RoslynMicrosoft.CodeAnalysis解析 C# 9 源码not模式对应语法节点UnaryPatternSyntax。入口位于 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cscase UnaryPatternSyntax unaryPattern: return new UnaryPattern(cx, unaryPattern, parent, child);实体类 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/UnaryPattern.cs 的实现internal class UnaryPattern : Expression { public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) : base(new ExpressionInfo(cx, cx.GetConvertedType(syntax), cx.CreateLocation(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, isCompilerGenerated: false, null)) { Pattern.Create(cx, syntax.Pattern, this, 0); } }关键细节提取器把UnaryPatternSyntax归类为ExprKind.NOT_PATTERN与 QL 侧NotPatternExpr关联的not_pattern_expr实体一一对应Pattern.Create(cx, syntax.Pattern, this, 0)递归提取not关键字之后的子模式syntax.Pattern以child 0挂到当前实体之下——这正是 QL 侧getPattern()返回this.getChild(0)的来源类被声明为internal且命名空间为Semmle.Extraction.CSharp.Entities.Expressions表明它是提取器内部实现细节外部仅通过 QL 类NotPatternExpr暴露。从源码结构看该提取分支位于Pattern.Create工厂方法的 switch 中与常量模式、递归模式、位置模式等并存说明not模式被当作一等公民接入既有的模式提取体系。分析库中的应用守卫分析对 not 模式的推理新增的 QL 类并非仅供 AST 查询展示而是被集成进核心分析库。最有代表性的是 csharp/ql/lib/semmle/code/csharp/controlflow/Guards.qll 中的守卫guard推理——数据流分析依靠守卫来精确描述分支条件下的值域。相等性测试的极性反转在equalityTest谓词中Guards.qllis表达式与常量模式的组合会被建模为相等性测试而not模式会翻转极性exists(IsExpr ie, PatternExpr pat | ie eqtest and ie.getExpr() left and ie.getPattern() pat | right pat.(ConstantPatternExpr) and polarity true or right pat.(NotPatternExpr).getPattern().(ConstantPatternExpr) and polarity false )也就是说x is 1被识别为正极性相等测试而x is not 1通过pat.(NotPatternExpr).getPattern().(ConstantPatternExpr)解包出常量子模式并标注为反极性不等测试。这样一来if (x is not 1)分支内的分析就能正确推导出x ! 1的约束。null 匹配的布尔取反patternMatchesNull谓词Guards.qll递归计算某模式是否匹配null其中对NotPatternExpr做了显式处理private boolean patternMatchesNull(PatternExpr pat) { pat instanceof NullLiteral and result true or not pat instanceof NullLiteral and not pat instanceof NotPatternExpr and not pat instanceof OrPatternExpr and not pat instanceof AndPatternExpr and result false or result patternMatchesNull(pat.(NotPatternExpr).getPattern()).booleanNot() or exists(OrPatternExpr ope | pat ope | ...) or exists(AndPatternExpr ape | pat ape | ...) }这里result patternMatchesNull(pat.(NotPatternExpr).getPattern()).booleanNot()直接对子模式的 null 匹配结果取反x is not null因此被正确判定为匹配 null 为假、匹配非 null 为真与or/and组合模式的递归规则共同构成完整的模式 null 语义。这也是c is not null这类判空守卫能够参与空指针相关分析与净化器建模的基础。测试验证control flow 图中的 not 模式覆盖仓库在 csharp/ql/test/library-tests/controlflow/graph/Patterns.cs 中提供了覆盖各种not用法的测试源码例如public static bool M2(char c) c is not a; // not 常量模式 public static bool M3(object c) c is not null ? c is 1 : c is 2; // not null 字面量 public static bool M4(object c) c is not Patterns { P1: 1 } u; // not 递归属性模式 public static string M5(int i) i switch { not 1 not 1, _ other }; // switch 表达式 public static string M6() 2 switch { not 2 impossible, 2 possible }; public static string M8(int i) i is 1 or not 2 ? not 2 : 2; // not 与 or 组合 public static string M9(int i) i is 1 and not 2 ? 1 : not 1; // not 与 and 组合对应的期望输出 BasicBlock.expected 中出现了形如After not ... [match]与not 1的控制流标签证明控制流图CFG构建阶段能够正确处理not模式的匹配节点及其后继分支覆盖了模式匹配成立/不成立两条路径。这说明本次变更不仅是纯语法层面的 AST 支持还贯通了 CFG 与守卫推理保证基于not模式的布尔逻辑不会在后续分析如可达性、数据流中丢失。使用建议与注意事项版本前提not模式是 C# 9 语法需要目标源码以支持 C# 9 的编译器/Roslyn 版本编译CodeQL 的 C# 提取器通过UnaryPatternSyntax识别因此对源码本身的工程配置没有额外要求只要分析数据库是由新版本提取器生成即可查询到NotPatternExpr在查询中的用法如需在自定义查询中匹配取非判断可用pat instanceof NotPatternExpr并调用pat.getPattern()取得被否定的子模式例如在Guards.qll中那样结合ConstantPatternExpr还原出被比较的常量如需匹配任意一元模式可使用父类UnaryPatternExpr它保留了未来扩展到其他一元模式若 C# 后续版本引入的余地组合模式遍历由于 Expr.qll 已把unary_pattern_expr纳入getAChildExpr()递归基于Expr的通用遍历类查询可以无感知地穿透not模式访问其内部子模式无需针对NotPatternExpr写特殊处理分支语义正确性not模式匹配null的语义由 Guards.qll 的递归规则保证与 C# 规范一致not null匹配所有非 null 值在编写依赖守卫推导的自定义数据流配置时可以直接复用该基础设施。小结2021-01-14-Unary-pattern.md这一变更说明虽然简短却标志着一个完整的支持链提取器UnaryPattern.csExprKind.NOT_PATTERN→ QL 类Expr.qll 中的UnaryPatternExpr/NotPatternExpr→ 分析库Guards.qll 的相等测试与 null 匹配推理→ 测试Patterns.cs 与 BasicBlock.expected。对于编写或扩展 C# 查询的开发者而言理解这两个类及其在守卫分析中的角色是让自定义分析正确处理 C# 9 模式匹配语义的关键一步。赞分享静态分析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点击查看免费下载相关推荐mermaid-ascii子图subgraph完全指南嵌套分组布局与标题渲染mermaid ascii子图subgraph完全指南嵌套分组布局与标题渲染 mermaid ascii 是一个在终端中渲染 Mermaid 图表的命令行工具静态分析SAST应用安全漏洞扫描代码质量CodeQL C 库 2.1.0 新特性深度解析函数指针调用解析、隐式声明识别与 C20 requires 表达式支持CodeQL C 库 2.1.0 新特性深度解析函数指针调用解析、隐式声明识别与 C20 requires 表达式支持 本篇文章围绕 CodeQL 仓静态分析SAST应用安全漏洞扫描代码质量CodeQL C 库 0.0.12 版本解析TaintTracking API 重构、Flow State 支持与模板隐式复制语义修复CodeQL C 库 0.0.12 版本解析TaintTracking API 重构、Flow State 支持与模板隐式复制语义修复 本文基于 cpp/静态分析SAST应用安全漏洞扫描代码质量上一篇OR-Tools优化算法实战3个核心场景教你如何高效解决复杂运筹问题下一篇颠覆传统PDF管理极简页面编辑工具如何让300页文档处理效率提升80%创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站