ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CodeQL 查询改进解析:cpp/implicit-bitfield-downcast 对 C++ 引用类型的隐式位域降级检测

CodeQL 查询改进解析:cpp/implicit-bitfield-downcast 对 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/C 查询cpp/implicit-bitfield-downcast的一次重要改进展开该查询原先只检测位域bitfield在隐式转换为更小的值类型时发生的高位截断问题而 2021-08-24 的变更见 cpp/old-change-notes/2021-08-24-implicit-downcast-from-bitfield.md使查询开始覆盖C 引用类型从而捕获更多真实缺陷true positive。读完本文你将理解位域隐式降级的危害原理、该查询的完整匹配逻辑、变更前后的行为差异以及如何在仓库测试用例中验证这一改进。变更背景位域的隐式截断为何是安全缺陷C/C 中的位域bitfield允许以精确到比特的粒度声明结构体成员例如unsigned int x : 24;表示该成员只占用 24 位。当位域被隐式转换为一个可表示位数更少的整数类型时高位的比特会被静默丢弃这一过程属于 CWE-681错误类型转换范畴。根据查询的官方说明文件 ImplicitDowncastFromBitfield.qhelp这种截断可能导致两类严重后果分配/迭代失真当位域用于表示数据结构中的元素个数被截断后会导致分配过小的缓冲区或迭代次数不足进而引发缓冲区溢出信息丢失位域高位的存储信息被静默丢弃。修复建议是改用足够宽的整数类型承载位域值或在使用显式转换explicit cast以明确截断意图。本次变更的核心覆盖 C 引用类型变更前的查询只关注位域向值类型如short、char的隐式转换。但在 C 中位域还会被绑定到引用上例如const char result m.x; // 将 24 位位域绑定到 char 引用此时同样会发生隐式降级截断而旧版查询无法发现这类缺陷。2021-08-24 的变更正是补齐了这一缺口使查询返回更多真实阳性结果。这一行为变化可以从查询源码中直接看到。查询实现原理逐行解析匹配逻辑查询本体位于 ImplicitDowncastFromBitfield.ql完整逻辑如下import cpp from BitField fi, VariableAccess va, Type fct where ( if va.getFullyConverted().getType() instanceof ReferenceType then fct va.getFullyConverted().getType().(ReferenceType).getBaseType() else fct va.getFullyConverted().getType() ) and fi.getNumBits() fct.getSize() * 8 and va.getExplicitlyConverted().getType().getSize() fct.getSize() and va.getTarget() fi and not fct.getUnspecifiedType() instanceof BoolType select va, Implicit downcast of bitfield $., fi, fi.toString()关键点逐条说明fct的取值分支本次变更的核心va.getFullyConverted()表示变量访问经过所有隐式转换后的最终表达式。若其类型是ReferenceType引用类型则fct取引用所指的基类型getBaseType()否则直接取最终表达式类型。也就是说const char result m.x中的fct会被解析为char从而与值类型场景统一处理。fi.getNumBits() fct.getSize() * 8位域的位宽大于目标类型的字节数乘以 8即目标类型无法容纳位域的全部比特这是“降级downcast”的判定条件。va.getExplicitlyConverted().getType().getSize() fct.getSize()原始显式转换前的表达式类型宽度大于目标类型宽度确认确实发生了收窄。这一条件排除了从宽度本身就较小的类型进行的转换。va.getTarget() fi确认该变量访问的目标正是被分析的位域成员。排除布尔类型not fct.getUnspecifiedType() instanceof BoolType避免对布尔位域误报因为转换为bool属于正常的真值判定语义不算缺陷。查询的元数据也值得注意它注册为cpp/implicit-bitfield-downcast严重级别为warning精度为high标签为reliability、correctness、types属于可靠性/正确性类缺陷检测。实战示例截断如何演变为缓冲区溢出查询自带的示例程序 ImplicitDowncastFromBitfield.c 直观展示了危害链条typedef struct { unsigned int x : 24; } my_struct; unsigned short getX(my_struct s ) { return s.x; //BAD: implicit truncation } unsigned int getXGood(my_struct s) { return s.x //GOOD: no truncation } int main (int argc, char **argv) { my_struct s; s.x USHORT_MAX 1; int* array calloc(sizeof(int), getX(s)); //BAD: buffer allocated is smaller than intended for (int i 0; i s.x; i) { array[i] i; } ... }分析要点位域x宽度为 24可容纳的最大值为 2^24 - 1显然大于unsigned short的 2^16 - 1getX返回unsigned short对s.x的隐式返回转换截断了高位USHORT_MAX 1被截为 0calloc依据被截断的值分配过小的缓冲区而循环却按未截断的s.x迭代最终越界写入array形成缓冲区溢出修复后的getXGood返回unsigned int宽度足以容纳 24 位位域分配与迭代一致代码安全。测试验证引用类型用例被正确检出仓库在 ImplicitDowncastFromBitfield 测试目录 中提供了针对本次变更的回归测试。核心测试文件 test.cpp 覆盖了多种正反用例int getX1(my_struct m) { return m.x; // GOOD —— 目标 int 足够宽 } short getX2(my_struct m) { return m.x; // $ Alert —— BAD截断 } short getX3(my_struct m) { return (short) m.x; // GOOD —— 显式转换 } bool getX4(my_struct m) { return m.x; // GOOD —— 布尔语义排除 } short getX5(my_struct m) { return (char) m.x; // GOOD —— 显式转换 } const char getx6(my_struct m) { const char result m.x; // $ Alert // BAD引用类型截断 return result; } const short getx7(my_struct m) { const short result (short) m.x; // GOOD —— 显式转换 return result; } const int getx8(my_struct m) { const int result m.x; // GOOD —— int 足够宽 return result; } const bool getx9(my_struct m) { const bool result m.x; // GOOD —— 布尔语义排除 return result; }其中getx6正是本次变更新增检测能力的直接体现24 位位域被隐式绑定到const char引用时发生截断被标记为告警而getx7通过显式(short)转换表达意图getx8因int足够宽、getx9因布尔类型被显式排除而均不告警。对应的期望输出 ImplicitDowncastFromBitfield.expected 精确记录了两处告警位置恰好与测试用例中的$ Alert注释一一对应test.cpp:10:11:10:11 | x | Implicit downcast of bitfield $. | test.cpp:2:6:2:6 | x | x | test.cpp:26:25:26:25 | x | Implicit downcast of bitfield $. | test.cpp:2:6:2:6 | x | x |第一处对应getX2中值类型的隐式返回转换第二处对应getx6中引用类型的隐式绑定——两行结果共同验证了查询同时覆盖值类型与引用类型两种场景且测试通过qlref机制与查询绑定见 ImplicitDowncastFromBitfield.qlref。如何复现与使用该查询查看查询实现ImplicitDowncastFromBitfield.ql查看完整示例与说明ImplicitDowncastFromBitfield.c 与 ImplicitDowncastFromBitfield.qhelp运行回归测试仓库测试套件test 目录下的qlref与.expected文件会将该查询应用于test.cpp并核对告警位置使用 CodeQL CLI 或 CodeQL for Visual Studio Code 对目标 C/C 工程运行此查询即可在结果中看到类似Implicit downcast of bitfield的告警信息。小结本次变更cpp/old-change-notes/2021-08-24-implicit-downcast-from-bitfield.md让cpp/implicit-bitfield-downcast查询从仅检测值类型收窄扩展到同时检测 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点击查看免费下载相关推荐如何用 Vitest 与 Testing Library 为 TanStack Router 代码路由写测试如何用 Vitest 与 Testing Library 为 TanStack Router 代码路由写测试 如果你的 TanStack Router 应用使用静态分析SAST应用安全漏洞扫描代码质量CodeQL C 安全查询解读循环条件中的宽类型比较检测cpp/comparison-with-wider-typeCodeQL C 安全查询解读循环条件中的宽类型比较检测cpp/comparison with wider type 在 C/C 代码中当循环条静态分析SAST应用安全漏洞扫描代码质量aisuite 如何运行 MCP 集成测试配置 Node.js 环境并区分免费的 mocked LLM 测试与真实 LLM 测试aisuite 如何运行 MCP 集成测试配置 Node.js 环境并区分免费的 mocked LLM 测试与真实 LLM 测试 aisuite 的 MCP静态分析SAST应用安全漏洞扫描代码质量上一篇SQLite-Vec双许可协议解析MIT与Apache双保险的开源选择下一篇Notion文件上传功能详解从本地文件到Notion页面的完整流程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表