
静态分析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/C 查询库 7.1.0 版本的官方发布说明cpp/ql/lib/change-notes/released/7.1.0.md逐条讲解新增的#embed指令 AST 支持、面向 flow states 的ParameterizedBarrierGuard数据流模块、MySQL 转义函数的 taint/barrier 建模、SummarizedCallable.propagatesFlow签名演进以及若干影响缓冲区溢出查询、守卫条件识别和asDefinition()结果的缺陷修复。读者读完可掌握这些 API 的底层实现位置、使用方式与对既有查询的潜在影响。一、版本概览7.1.0 是 CodeQL C/C 查询库位于 cpp/ql的一个功能与修复并重的版本改动集中在四个方面新增功能#embed预处理器指令建模、参数化数据流屏障模块分析改进缓冲区尺寸推断修正、MySQL 转义函数建模、模型摘要谓词签名扩展缺陷修复GuardCondition对二元逻辑运算的识别、Node.asDefinition()的赋值结果缺失。下文按发布说明的章节顺序展开并深入对应源码验证每一条改动的真实形态。二、新增功能C23 / C26#embed指令建模7.1.0 为 C23 与 C26 标准引入的#embed预处理器指令新增了Embed类它是PreprocessorDirective的子类。该类的实现位于 cpp/ql/lib/semmle/code/cpp/Preprocessor.qll/** * A C23 or C26 #embed preprocessor directive. For example, the following code * contains one Embed directive: * cpp * char arr[] { * #embed bin * }; * */ class Embed extends PreprocessorDirective, ppd_embed { override string toString() { result #embed this.getIncludeText() } /** * Gets the token which occurs after #embed, for example filename * or filename. */ string getIncludeText() { result this.getHead() } /** * Gets the file directly embedded by this #embed. */ File getEmbeddedFile() { embeds(underlyingElement(this), unresolveElement(result)) } }从源码结构可以确认以下使用方式#embed允许在源文件中直接嵌入二进制文件内容典型场景是数组初始化char arr[] { #embed bin };Embed.toString()返回#embed filename形式的文本表示与其它指令类的toString风格一致getIncludeText()返回指令头 token即filename或filename形式的包含文本getEmbeddedFile()通过底层的embeds关系返回被嵌入的File对象可用于进一步分析被嵌入资源的尺寸、内容或访问方式。该类的存在意味着查询作者可以直接在 QL 中匹配#embed指令例如检查嵌入资源的尺寸是否越界或确认嵌入用法是否符合安全策略。需要注意#embed是 C23 / C26 新标准特性只有在新标准编译环境下才会产生对应的ppd_embed数据库条目。三、新增功能支持 flow states 的参数化数据流屏障模块3.1 背景普通 BarrierGuard 的局限数据流分析中的isBarrier/isSanitizer谓词用于切断污点传播。传统上DataFlow::BarrierGuard见 cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll要求使用者提供一个不带额外参数的守卫检查谓词。但当数据流配置使用了flow states流状态时守卫判断往往需要读取当前状态才能决定是否构成屏障此时普通的无参签名便无法满足需求。3.2 参数化模块的实现7.1.0 新增的ParameterizedBarrierGuard与ParameterizedInstructionBarrierGuard正是为解决这一问题而设计。前者针对“守卫校验某个表达式”的场景后者针对“守卫校验某条 IR 指令”的场景二者都允许额外携带一个参数Pmodule ParameterizedBarrierGuardParamSig P, WithParamP::guardChecksSig/4 guardChecks { ... Node getABarrierNode(P p) { ... } Node getABarrierNode() { result getABarrierNode(_) } Node getAnIndirectBarrierNode(P p) { result getAnIndirectBarrierNode(_, p) } Node getAnIndirectBarrierNode() { result getAnIndirectBarrierNode(_) } }关键点模块参数P是一个签名类ParamSig实际传入时可以是Unit等价于无参数也可以是一个携带状态信息的类守卫检查签名从 3 元谓词扩展为 4 元谓词guardChecksSig(IRGuardCondition g, Expr e, boolean branch, P param)参数param在每次判断时被传入从而可以在不同 flow state 下做出不同决策模块在内部同时结合 IR 的值编号ValueNumber与 SSA 实现SsaImpl::BarrierGuardP, guardChecksNode/4计算屏障节点getAnIndirectBarrierNode系列则用于指针间接表达式*p场景。从源码可见原有BarrierGuard与InstructionBarrierGuard现在被重新实现为参数化版本的Unit特例见 DataFlowUtil.qll 与 DataFlowUtil.qll从而保证 API 向后兼容同时为高级用户提供更强的表达能力。3.3 使用示例以下示意如何在带 flow state 的配置中定义屏障具体谓词签名以你的配置为准signature class StateSig; predicate myGuardChecks( IRGuardCondition g, Expr e, boolean branch, StateSig state ) { // 依据当前 flow state 决定 e 是否被安全校验 state.requiresBarrier(e) and branch true } predicate isBarrier(DataFlow::Node barrier, StateSig state) { barrier DataFlow::ParameterizedBarrierGuardStateSig, myGuardChecks/4::getABarrierNode(state) }若实际不需要状态参数可以直接沿用无参版本DataFlow::BarrierGuardmyGuardChecks/3::getABarrierNode()二者在 7.1.0 中行为一致。四、分析改进缓冲区查询误报减少与 MySQL 建模4.1 Buffer.qll 对损坏数据库的健壮性修复发布说明指出Buffer.qll在部分损坏的数据库上不再报告错误的缓冲区尺寸从而减少了以下查询的误报cpp/static-buffer-overflowcpp/overflow-buffercpp/badly-bounded-writecpp/overrunning-writecpp/overrunning-write-with-floatcpp/very-likely-overrunning-write这类缓冲区相关的核心逻辑位于 cpp/ql/lib/semmle/code/cpp/models/implementations/Buffer.qll该库被上述缓冲区溢出查询共同引用。含义是当数据库中缓冲区尺寸信息缺失或不一致时库会保守地不产出错误的尺寸结论而非强行给出一个可能导致误报的数值。对于依赖这些查询的扫描结果而言此项修复直接提升了精确率。4.2 MySQL 转义函数的 taint 摘要与 SQL 注入屏障7.1.0 为 MySQL 的两个转义函数新增了建模配置位于 cpp/ql/lib/ext/MySql.model.yml# taint 摘要第二个参数待转义字符串的污点流向第一个参数输出缓冲区 - [, , False, mysql_real_escape_string, , , Argument[*2], Argument[*1], taint, manual] - [, , False, mysql_real_escape_string_quote, , , Argument[*2], Argument[*1], taint, manual] # sql-injection 屏障第一个参数输出缓冲区被标记为安全的 SQL 数据 - [, , False, mysql_real_escape_string, , , Argument[*1], sql-injection, manual] - [, , False, mysql_real_escape_string_quote, , , Argument[*1], sql-injection, manual]这两组模型的实际效果taint 摘要模型mysql_real_escape_string(dst, src, ...)与mysql_real_escape_string_quote(dst, src, ...)的第二个参数到第一个参数构成 taint 传播边即经过转义后的字符串仍携带经过变换的污点sql-injection 屏障模型转义后的第一个参数输出缓冲区被标记为sql-injection类屏障因为经过正确转义的内容不会再导致 SQL 注入。两者配合意味着污点从不可信输入流入src经转义函数处理后写入dstdst上的内容在进入 SQL 拼接时被视为已消毒。这是对cpp/sql-injection查询数据流路径的精确补充manual表示由人工确认的模型来源。4.3 SummarizedCallable.propagatesFlow 签名扩展SummarizedCallable是外部流建模的核心抽象其propagatesFlow谓词在 7.1.0 中被扩展为包含Provenance p与boolean isExact两列作为代价SummarizedCallable.hasProvenance与SummarizedCallable.hasExactModel两个谓词被移除。这一变化体现在适配器类中见 cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qlloverride predicate propagatesFlow( string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model ) { input input_ and output output_ and (if kind value then preservesValue true else preservesValue false) and p p_ and isExact true and model model_ }对查询作者而言这是一次破坏性变更如果自定义代码直接引用了hasProvenance或hasExactModel在升级到 7.1.0 后需要改用propagatesFlow/6谓词通过其新增的p与isExact列完成等价判断。该改动把原本分散的元数据查询统一收拢到主谓词上使模型信息来源 provenance、是否精确匹配与传播关系在同一处可见。五、缺陷修复5.1 GuardCondition 对二元逻辑运算符的识别GuardCondition库此前存在一个缺陷某些由二元逻辑运算符、||构成的守卫条件无法被识别为 guard condition。修复后依赖GuardCondition的查询可能得到改进的结果例如更准确地判定某个表达式在分支上是否被安全校验。从源码结构看IR 守卫条件的实现位于 cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll其中GuardConditionFromBinaryLogicalOperator约 IRGuards.qll 起负责把/||及其子表达式组合成守卫条件并推导各部分的真值关系partIsTrue/GuardValue partValue。此次修复正是围绕这一组合逻辑展开直接影响依赖守卫分析的库如GuardCondition驱动的屏障/净化器推断以及cpp/ql/lib/semmle/code/cpp/controlflow/Guards.qll中的使用方。5.2 Node.asDefinition() 对部分赋值缺失结果Node.asDefinition()此前在某些赋值场景下不返回结果。该谓词用于把数据流节点映射为对应的“定义”def是 SSA 与数据流分析中把表达式节点与定义节点对齐的关键步骤。修复后这类赋值可以推断与结构化的赋值表达式、复合赋值或特定转换表达式相关能够正确返回定义节点从而避免相关数据流查询在这些赋值处丢失路径。六、升级与兼容性提示综合 7.1.0 的改动在升级查询库时需要注意破坏性 API 变更SummarizedCallable.hasProvenance与SummarizedCallable.hasExactModel已被移除相关判断请迁移到propagatesFlow的p与isExact列新增 APIEmbed、DataFlow::ParameterizedBarrierGuard、DataFlow::ParameterizedInstructionBarrierGuard为新增加入不存在兼容性问题行为变化缓冲区溢出相关查询误报减少、GuardCondition相关查询结果可能增多、asDefinition()覆盖范围扩大运行查询套件时可能观察到结果集差异属于预期内的修复效果依赖说明#embed支持依赖 C23 / C26 编译环境旧标准代码不会生成对应指令节点。七、总结7.1.0 版本在三个维度上推进了 C/C 查询库的能力面向新语言标准补齐 AST 建模#embed、面向高级数据流场景开放更强的屏障抽象参数化 BarrierGuard 模块、以及通过 MySQL 模型与缓冲区推断修复提升既有安全查询的精确率。同时propagatesFlow的签名演进提醒查询作者关注破坏性变更。对于希望深入源码验证的读者建议从 cpp/ql/lib/semmle/code/cpp/Preprocessor.qll 与 cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll 两个文件入手前者可查看Embed类全貌后者可对照参数化屏障模块与无参版本的内部复用关系。赞分享静态分析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/C 库 3.2.0 变更深度解析数据流屏障、C20/23 语法建模与模板分析增强CodeQL C/C 库 3.2.0 变更深度解析数据流屏障、C20/23 语法建模与模板分析增强 本篇文章聚焦 CodeQL 开源仓库中 C/C静态分析SAST应用安全漏洞扫描代码质量CodeQL C/C 分析库 5.3.0 版本解析弃用 API、数据流新谓词与 Arm/OCI 模型增强CodeQL C/C 分析库 5.3.0 版本解析弃用 API、数据流新谓词与 Arm/OCI 模型增强 本文以 CodeQL 仓库中 cpp/ql/li静态分析SAST应用安全漏洞扫描代码质量CodeQL C 库 10.1.0 更新详解getSwitchCase 谓词、数据扩展屏障与 Strsafe 污点流模型CodeQL C 库 10.1.0 更新详解getSwitchCase 谓词、数据扩展屏障与 Strsafe 污点流模型 CodeQL C 分析库在静态分析SAST应用安全漏洞扫描代码质量创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考