ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CodeQL C++ 分析库 5.5.0 变更详解:PchFile 预编译头建模、ComPtr 数据流摘要与虚函数分派精度提升

CodeQL C++ 分析库 5.5.0 变更详解:PchFile 预编译头建模、ComPtr 数据流摘要与虚函数分派精度提升 静态分析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 分析库codeql/cpp-all5.5.0 版本的发布说明展开聚焦三项核心变更新增的PchFile类如何对预编译头PCH文件进行建模、Microsoft::WRL::ComPtr数据流摘要flow summaries的引入方式以及新一代 dataflow/taint-tracking 库对虚函数调用分派解析的精度改进。读者可通过本文理解这三项能力的底层实现QL 类定义、dbscheme 表结构、模型文件语法与分派算法并直接应用于自己项目的 C 数据流与污点分析查询。版本背景与变更总览5.5.0 是codeql/cpp-all查询库的迭代版本其变更记录位于 cpp/ql/lib/change-notes/released/5.5.0.md同时被完整收录进库的 CHANGELOG.md。该版本的改动可以分为两类New Features新功能新增PchFile类用于表示项目编译过程中创建与使用的预编译头文件。Minor Analysis Improvements次要分析改进为Microsoft::WRL::ComPtr成员函数补充数据流摘要新一代数据流/污点追踪库对虚函数调用进行更精确的解析从而减少误报。下文将逐项结合仓库源码、dbscheme 表结构与模型文件展开说明。一、PchFile为预编译头文件建立分析实体1.1 为什么要建模 PCH 文件预编译头Precompiled Header, PCH是 C/C 构建流程中常见的加速手段编译器把大量稳定头文件预先解析并序列化为二进制形式后续编译单元直接复用避免重复解析。对 CodeQL 而言PCH 文件属于构建过程产物传统文件模型中缺乏专门的实体来表示它导致与 PCH 相关的创建、引用关系难以被查询语言直接访问。5.5.0 新增的PchFile类填补了这一空白。该类的完整实现位于 cpp/ql/lib/semmle/code/cpp/PchFile.qll并已被 cpp/ql/lib/cpp.qll 导入意味着在任意 C 查询中可以直接使用该类型。1.2 PchFile 类的 QL 定义与成员谓词PchFile的类定义非常精简继承自底层实体pchimport semmle.code.cpp.File class PchFile extends pch { string toString() { result PCH for this.getHeaderFile() } File getHeaderFile() { pch_creations(this, _, result) } File getAUse() { pch_uses(this, _, result) } }三个核心成员谓词分别回答了 PCH 分析中最关键的三个问题谓词返回值语义底层关系toString()string人类可读表示形如PCH for 头文件路径—getHeaderFile()File生成该 PCH 的源头文件pch_creationsgetAUse()File某个包含了该 PCH 的源文件pch_uses其中getHeaderFile与getAUse直接映射到 dbscheme 中两条关系表。在 cpp/ql/lib/semmlecode.cpp.dbscheme 中可以看到它们的定义pch_uses( int pch: pch ref, int compilation: compilation ref, int id: file ref ) #keyset[pch, compilation] pch_creations( int pch: pch, int compilation: compilation ref, int from: file ref )pch_creations记录(pch, compilation, from)三元组其中from是生成该 PCH 的头文件#keyset[pch, compilation]声明了pch与compilation构成唯一键即同一编译任务下每个 PCH 只记录一次创建。pch_uses记录(pch, compilation, id)id是包含该 PCH 的源文件pch通过ref指向pch实体。这套表结构意味着 CodeQL 数据库已经能够表达“哪个头文件生成了哪个 PCH又被哪些源文件复用”的完整关系图谱而PchFile类只是把这两张表封装成了符合 QL 习惯的面向对象接口。1.3 实战用 PchFile 编写查询基于上述定义可以直接编写查询来回答工程实践中的常见问题。例如查找所有未被任何源文件复用的 PCH潜在的构建冗余或查找某个头文件对应的 PCH 及其使用者import cpp // 找出由 config.h 生成的 PCH以及所有复用了它的源文件 from PchFile p, File header where header p.getHeaderFile() and header.getAbsolutePath() C:/src/config.h select p, p.getAUse() as user再如统计每个头文件生成的 PCH 数量评估预编译头的粒度分布import cpp from File header, PchFile p where p.getHeaderFile() header select header, count(p) as pchCount group by header需要注意PchFile实例的有无取决于抽取器extractor是否在构建追踪阶段采集了 PCH 相关数据它主要服务于那些确实启用预编译头、且构建过程被完整追踪的项目。二、为 Microsoft::WRL::ComPtr 添加数据流摘要2.1 背景ComPtr 与 CodeQL 模型文件Microsoft::WRL::ComPtrT是 Windows Runtime C Template Library (WRL) 中广泛使用的智能指针负责管理 COM 对象的引用计数。它的成员函数如Attach、Detach、CopyTo、GetAddressOf、operator-等会把内部持有的指针“搬运”到参数、返回值或引用参数中。如果不建模这些搬运关系数据流/污点分析会把大量真实的指针流动切断造成漏报。CodeQL 的 C 库通过**模型文件model files**声明这类库 API 的数据流行为它们位于 cpp/ql/lib/ext/并通过 cpp/ql/lib/qlpack.yml 中的dataExtensions: ext/*.model.yml挂载到codeql/cpp-all包中。2.2 ComPtr 摘要清单逐条解读5.5.0 在 ComPtr.model.yml 中为ComPtr的主类模板与ComPtrT特化补充了完整的 value 型摘要同时在 ComPtrRef.model.yml 中为内部辅助类Microsoft::WRL::Details::ComPtrRef建模。模型行遵循统一格式namespace, type, subtypes, name, signature, ext, input, output, kind, provenance其中kind统一为value值传递流provenance为manual人工编写。以下摘录并解读最常用的几条成员函数输入input输出output语义构造函数ComPtrT(T *)Argument[*0]Argument[-1].Element[]裸指针存入this指向的元素拷贝/移动构造Argument[*0].Element[]Argument[-1].Element[]元素在智能指针间流转AttachArgument[*0]Argument[-1].Element[]接管裸指针DetachArgument[-1].Element[]ReturnValue[*]释放所有权并返回裸指针GetArgument[-1].Element[]ReturnValue[*]返回内部裸指针GetAddressOfArgument[-1].Element[]ReturnValue[**]返回内部指针的地址CopyTo(T **)Argument[-1].Element[]Argument[**0]复制到输出参数operator-Argument[-1].Element[]ReturnValue[*]解引用访问成员operator裸指针与智能指针各重载Argument[*0]Argument[-1].Element[]/ReturnValue[*].Element[]赋值搬运ComPtrRef.model.yml则覆盖了operator*、operator void**、ReleaseAndGetAddressOf等间接访问路径例如operator void**的摘要Argument[-1].Element[] - ReturnValue[**]表示通过ptr这种形式把内部元素以双重间接方式泄露到返回值中——这正是ReleaseAndGetAddressOf风格 API 的典型数据流模式。语法中的[*]、[**]表示按值解引用dereference层数Element[]表示容器元素的取值。理解这些标注可以帮助读者自行扩展其他智能指针如CComPtr、winrt::com_ptr的模型。2.3 模型文件的挂载与验证方式模型文件通过dataExtensions声明自动生效无需修改查询代码。若需验证某条摘要是否被加载可以在查询中引入semmle.code.cpp.dataflow.new.DataFlow构造一个从ComPtr内部指针到目标 sink 的小型数据流测试运行codeql test run执行对应的集成测试比对.expected输出检查数据库的 model 诊断信息若启用诊断输出。从仓库结构看ComPtr摘要集中于Microsoft::WRL命名空间主类未覆盖的成员如QueryInterface的显式特化路径仍可依赖通用虚函数分派与上一节所述的类型解析来兜底。三、虚函数调用解析精度改进减少数据流误报3.1 改进点概述5.5.0 的另一项关键改动是新一代数据流/污点追踪库semmle.code.cpp.dataflow.new.DataFlow与semmle.code.cpp.dataflow.new.TaintTracking在解析虚函数调用时更加精确显著减少了运行数据流/污点查询时因“分派目标过多”而产生的误报。C 中通过基类指针或引用调用虚函数时静态类型只能给出声明类运行时实际调用的是某个派生类的重写。若数据流分析把所有可能的重写实现全部纳入调用图那么每个虚调用点都会产生大量分支污染路径剧增误报随之而来。3.2 底层实现VirtualDispatch 模块分派逻辑的核心是 cpp/ql/lib/semmle/code/cpp/dispatch/VirtualDispatchPrototype.qll 中的VirtualDispatch模块。其入口谓词getAViableTarget(Call c)的逻辑为若调用是虚调用c.(FunctionCall).isVirtual()且目标为成员函数则基于限定符表达式qualifier的静态类型做可行性分析返回所有可能的实现否则直接返回c.getTarget()。可行性分析的核心在getAViableVirtualCallTargetprivate Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) { exists(Class qualifierSubType | result getAPossibleImplementation(staticTarget) and qualifierType qualifierSubType.getABaseClass*() and mayInherit(qualifierSubType, result) and not cannotInherit(qualifierSubType, result) ) }它的含义是只有满足以下条件的重写实现才被纳入候选集——该实现是staticTarget的直接或传递重写getAnOverridingFunction*()限定符静态类型是某个子类型的基类该子类型可能继承这个实现mayInherit并且没有在继承链上重写掉它cannotInherit通过override.overrides(f)排除被覆盖的实现。模块中还包含两个重要的性能/精度取舍对IUnknownCOM 接口其子类型与重写数量在大型数据库上可达数万直接忽略——既排除其作为限定符类型getCallQualifierType中not result.hasName(IUnknown)也排除其成员函数作为候选getAPossibleImplementation中not staticTarget.getDeclaringType().hasName(IUnknown)。从源码结构看这一特判正是为了控制分派候选集的爆炸式增长属于工程上典型的“精度与规模权衡”。3.3 新一代数据流库如何接入分派信息在 IR 数据流实现中分派结果被封装为TrackVirtualDispatchmethodDispatchSig/1 virtualDispatch0模块见 cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qllprivate module TrackVirtualDispatchmethodDispatchSig/1 virtualDispatch0 { private DataFlowPrivate::DataFlowCallable dispatch(DataFlowPrivate::DataFlowCall c) { result nonVirtualDispatch(c) or result virtualDispatch0(c) } ... }即每个虚调用点的可能目标 静态非虚解析结果 ∪ 传入的虚分派函数给出的候选目标。DataFlowDispatch.qll中通过d1/d2/d3/d4/d5等多档参数实例化该模块形成分派深度可控的解析策略。5.5.0 的改进本质上是收紧了virtualDispatch0这类谓词返回的候选集合从“所有静态可见的重写”收敛为“基于限定符类型可行性分析后的重写”从而在保留真实路径的同时剪除大量不可能分支。3.4 对查询编写者的影响与验证影响凡是基于semmle.code.cpp.dataflow.new.*编写的安全查询如命令注入、缓冲区溢出、释放后使用等在含大量多态类型的代码库上的误报都会下降调用图相关的分析结果也会随之收敛。验证方式可在 cpp/ql/test 目录中寻找数据流/污点相关的.qlref测试用例运行codeql test run后对比.expected文件观察虚调用场景下路径数量的变化也可以直接在自己项目的库上运行unresolved-call或基于新数据流库的查询做前后对比。兼容性旧版数据流库semmle.code.cpp.dataflow.DataFlow等不受影响本次精度提升仅作用于新库迁移到新库的查询才会获得收益。四、升级与回归风险提示结果变化方向PchFile是纯新增实体不影响既有查询结果ComPtr摘要可能让原本被切断的路径连通导致部分基于 WRL 代码的查询新增结果属于预期修复虚分派收紧则主要减少误报但也可能剪除极少数依赖“不可能目标”的异常路径建议在大型多态代码库上先做结果 diff。旧库兼容若查询仍依赖旧版数据流库本版本无行为变化如需享受虚分派精度收益应将查询迁移至semmle.code.cpp.dataflow.new.DataFlow/TaintTracking。模型扩展边界ComPtr摘要未覆盖IUnknown相关成员的分派排除逻辑二者互补前者补齐智能指针的数据流搬运后者控制 COM 接口重写爆炸共同服务于 Windows 平台的 COM/WRL 代码分析场景。结语CodeQL C 库 5.5.0 的三项变更分别补强了“构建产物建模”PchFile、“库 API 数据流语义”ComPtr摘要与“调用图精度”虚分派收敛三个维度。其中PchFile的 dbscheme 表结构与 QL 封装、模型文件的input/output语法、以及VirtualDispatch的可行性剪枝算法都可以作为读者继续深入 CodeQL C 库内部实现、乃至自行扩展其他智能指针模型的直接参考。相关实现文件与测试均可在此仓库的 cpp/ql/lib 目录下继续追踪研读。赞分享静态分析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点击查看免费下载相关推荐DDrawCompat终极指南免费解决Windows老游戏兼容性问题DDrawCompat终极指南免费解决Windows老游戏兼容性问题 你是否曾经在Windows 10或11上尝试运行那些经典的老游戏却遭遇黑屏、闪退、画面静态分析SAST应用安全漏洞扫描代码质量CodeQL C 查询库 0.10.0 版本要点IR 非返回函数分析与数据流 asDefiningArgument 语义变更CodeQL C 查询库 0.10.0 版本要点IR 非返回函数分析与数据流 asDefiningArgument 语义变更 本篇技术指南聚焦 CodeQ静态分析SAST应用安全漏洞扫描代码质量CodeQL C/C 库 3.2.0 变更深度解析数据流屏障、C20/23 语法建模与模板分析增强CodeQL C/C 库 3.2.0 变更深度解析数据流屏障、C20/23 语法建模与模板分析增强 本篇文章聚焦 CodeQL 开源仓库中 C/C静态分析SAST应用安全漏洞扫描代码质量上一篇深入解析 chezmoi 的 promptChoiceOnce 初始化模板函数交互式选择与数据持久化的结合下一篇CANN ops-transformer 算子库 CausalConv1d 深度指南NPU 上 Mamba 类模型的因果一维卷积实现与 aclnn/PyTorch 双接口调用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表