ARTICLE DETAIL

资讯详情

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

Cppcheck 空指针检查器详解:nullPointerArithmeticOutOfMemory(内存分配失败后的指针算术)

Cppcheck 空指针检查器详解:nullPointerArithmeticOutOfMemory(内存分配失败后的指针算术) 开发工具静态分析代码质量质量保障【免费下载链接】cppcheckstatic analysis of C/C code项目地址https://gitcode.com/gh_mirrors/cpp/cppcheck点击查看免费下载本篇技术指南围绕 Cppcheck 静态分析器的nullPointerArithmeticOutOfMemory检查器展开说明它如何在 C/C 代码中识别内存分配函数可能返回 NULL、却未经检查就对结果指针做算术运算的未定义行为。读完本文你将掌握该检查器的触发条件、消息格式、底层 ValueFlow 实现原理以及它在 lib/checknullpointer.cpp 与 test/testnullpointer.cpp 中的真实工作方式并学会编写与之配套的修复方案与回归测试。检查器速览属性值检查器 IDnullPointerArithmeticOutOfMemory默认消息If memory allocation fails: pointer addition with NULL pointer.类别CategoryUndefined Behaviour未定义行为严重度SeverityError适用语言C/C相关 CWECWE-682计算错误见源码中CWE_INCORRECT_CALCULATION该检查器属于 Cppcheck 空指针检查族CheckNullPointer源码位于 lib/checknullpointer.cpp相关文档即本文件 man/checkers/nullPointerArithmeticOutOfMemory.md。问题本质分配失败与指针算术为什么不能共存原文档的描述非常简洁对来自可能失败并返回 NULL的内存分配函数如malloc以及某些配置下的new返回的指针在未先检查分配是否成功的情况下直接执行指针算术运算。关键点在于算术与解引用的区别*(p2) 0这类代码中即使第一步p2并不解引用任何内存只要p实际为 NULLp2本身就是未定义行为。因此Cppcheck 不会等到真正解引用那属于nullPointerOutOfMemory检查器才报告——在内存压力下任何作用于分配结果的下一个操作都可能踩中 UB。文档的 Motivation 段落将其与 nullPointerOutOfMemory.md 直接对齐假设分配永远成功意味着把可能为 NULL 的指针继续用于算术甚至比较、索引都是错误的。若分配结果被用于解引用则报告nullPointerOutOfMemory若仅用于算术、-、、-、、--则报告本检查器。触发条件与检测逻辑从源码看实现该检查器不是独立的检测函数而是CheckNullPointerImpl::arithmetic()在识别到空指针算术后、根据 ValueFlow 中该空指针可能来自分配失败这一属性动态升级 ID 的结果。核心流程如下。第一步扫描所有函数体内的算术运算符在 lib/checknullpointer.cpp#L480-L516 的arithmetic()中检查器遍历符号数据库中的每个函数作用域用Token::Match(tok, -|||-||--)定位所有算术运算节点随后通过astOperand1()/astOperand2()判断哪个操作数是指针类型valueType()-pointer ! 0确认另一个操作数是整数isIntegral()排除指针与浮点等非法组合若数值操作数在 ValueFlow 中确定为0则跳过——与 0 的算术不告警从指针操作数上取 ValueFlow 值pointerOperand-getValue(0)若其可能为 NULL 且存在条件分支则发出nullPointerArithmeticRedundantCheck警告见下文否则进入错误上报。第二步根据空指针来源动态生成 ID在 pointerArithmeticError()lib/checknullpointer.cpp#L527-L555 中错误消息与 ID 由 ValueFlow 值的unknownFunctionReturn属性决定普通场景ID 为nullPointerArithmetic消息形如Pointer addition with NULL pointer.减法场景为Overflow in pointer arithmetic, NULL pointer is subtracted.空指针来自内存分配失败UnknownFunctionReturn::outOfMemory消息前缀改为If memory allocation fails: ...首字母小写ID 追加为nullPointerArithmeticOutOfMemory空指针来自资源分配失败UnknownFunctionReturn::outOfResources前缀为If resource allocation fails: ...ID 追加为nullPointerArithmeticOutOfResources。这也解释了为什么检查器 ID 会携带OutOfMemory后缀——它是同一检测路径在 ValueFlow 证据加持下的细化分类便于用户用--suppressnullPointerArithmeticOutOfMemory单独压制或按 ID 统计。该错误固定以Severity::error上报并关联CWE_INCORRECT_CALCULATIONCWE-682Certainty视 ValueFlow 证据是否确定为inconclusive。若结论是不确定的inconclusive需要用户在命令行启用--inconclusive才会报告参见arithmetic()中对mSettings.certainty.isEnabled(Certainty::inconclusive)的判断。第三步与条件分支重叠时降级为警告当 ValueFlow 显示指针可能为 NULL 但已经存在相关条件检查时arithmetic()会改走redundantConditionWarning()lib/checknullpointer.cpp#L557-L574以Severity::warning上报 ID 为nullPointerArithmeticRedundantCheck的消息如Either the condition !s is redundant or there is pointer arithmetic with NULL pointer.提示条件冗余或算术仍可能越界属于同族检查器的冗余条件变体。底层原理ValueFlow 如何标记分配可能失败nullPointerArithmeticOutOfMemory之所以能识别出空指针来自malloc等分配函数依赖 ValueFlow 对未知函数返回的建模实现在 lib/valueflow.cpp#L7225-L7249首先通过settings.library.getAllocFuncInfo()判断当前调用是否登记为库配置中的分配函数若该函数带noFail标志即不可能失败则不注入NULL 可能值若该函数返回指针且无noFail则注入一个possible的值0并在错误路径errorPath中记录Assuming allocation function fails关键分流若分配函数属于Library::ismemory(groupId)即库配置将其归为内存分配如malloc、realloc、new则标记unknownFunctionReturn outOfMemory否则标记为outOfResources。也就是说哪些函数会被当作 failable 分配函数由 Cppcheck 的库配置文件决定例如 cfg/std.cfg、cfg/posix.cfg 中的函数定义及其noreturn、alloc、noFail等属性。这解释了原文档中newin some configurations的措辞new是否被视为可失败的分配函数取决于使用的平台配置与库配置。pointerArithmeticError()正是读取这个unknownFunctionReturn属性来区分...OutOfMemory与...OutOfResources的。真实测试用例一行代码复现与验证仓库自带针对该检查器的回归测试位于 test/testnullpointer.cpp#L4399-L4419 的nullpointerOutOfMemory()测试中void f() { int *p malloc(10); *(p2) 0; free(p); }期望输出[test.cpp:3:8]: (error) If memory allocation fails: pointer addition with NULL pointer. [nullPointerArithmeticOutOfMemory]注意测试断言的是第 3 行*(p2)中的加法表达式——malloc的返回值被 ValueFlow 标记为可能为 NULL随后直接参与2算术于是以nullPointerArithmeticOutOfMemory上报而同一测试中仅做解引用的*p 0则对应报告nullPointerOutOfMemorywarning 级别。两行代码的对照恰好印证了原文档中算术版 / 解引用版两个检查器的分工。手工验证同样简单将上述代码保存为test.c后执行cppcheck test.c即可复现如需报告不确定证据追加--inconclusive。检查器属于Severity::error默认即启用无需额外--enable其 ID 同时登记在 lib/settings.cpp第 389、453、515 行附近的检查器清单中参与命令行层面的开关与压制管理。相邻检查器与组合使用原文档的 Related checkers 部分定义了该检查器的亲属关系结合源码可以更精确地理解nullPointerArithmetic.md同样的算术检测逻辑但空指针来源不特定于可失败的分配函数例如可能是未初始化、显式赋 NULL 等ID 不带OutOfMemory后缀消息为Pointer addition with NULL pointer.nullPointerOutOfMemory.md同一 ValueFlow 证据分配失败下的直接解引用版本消息为If memory allocation fails, then there is a possible null pointer dereference: p通常以 warning 上报nullPointerArithmeticRedundantCheck存在相关条件检查时的警告变体用于提示条件冗余或算术越界。此外在 lib/checkersidmapping.cpp 中该检查族被映射到 MISRA C 规则a5-3-2CERTEXP34等合规标准意味着在启用 MISRA/CERT 配置的项目中nullPointerArithmetic系列会作为对应规则的落地实现被触发适合需要做安全合规审计的团队。修复建议修复模式非常直接在使用分配结果之前检查其是否为空。void f() { int *p malloc(10); if (p NULL) { // 处理分配失败记录错误、返回或走备选路径 return; } *(p 2) 0; free(p); }加入检查后ValueFlow 会在p2处推导出p非空不再上报nullPointerArithmeticOutOfMemory。若代码必须让分配结果裸奔参与算术则应改用不会失败或带异常语义的分配方式如std::vector、new的nothrow与显式检查组合等确保分配失败后的任何指针操作都不进入未定义行为区间。小结nullPointerArithmeticOutOfMemory是 Cppcheck 空指针检查族中专门针对可失败内存分配 未经检查的指针算术的 Error 级检查器。它并非独立算法而是CheckNullPointer::arithmetic()借助 ValueFlow 的unknownFunctionReturn::outOfMemory证据对通用空指针算术错误做的细化分类。理解它的关键链条是库配置cfg 系列声明分配函数 → ValueFlow 注入可能为 NULLlib/valueflow.cpp→arithmetic()扫描算术运算符 →pointerArithmeticError()依据证据拼接消息与 ID。配合 test/testnullpointer.cpp 中的回归用例你可以在自己的 CI 流程中轻松复现、压制或扩展这一检查。赞分享开发工具静态分析代码质量质量保障【免费下载链接】cppcheckstatic analysis of C/C code项目地址https://gitcode.com/gh_mirrors/cpp/cppcheck点击查看免费下载相关推荐Cppcheck 检查器详解arithOperationsOnVoidPointer 与 void* 指针算术的可移植性隐患Cppcheck 检查器详解arithOperationsOnVoidPointer 与 void 指针算术的可移植性隐患 导读 arithOperation开发工具静态分析代码质量质量保障cppcheck 跨编译单元Whole-Program空指针解引用检测ctunullpointer 检查器完全指南cppcheck 跨编译单元Whole Program空指针解引用检测ctunullpointer 检查器完全指南 本文围绕 cppcheck 的 ctu开发工具静态分析代码质量质量保障cppcheck 的 deallocret 检查器捕获“释放后返回指针”的未定义行为cppcheck 的 deallocret 检查器捕获“释放后返回指针”的未定义行为 导读 deallocret 是 cppcheck 内置的 C/C 静开发工具静态分析代码质量质量保障上一篇3步打造高性能多线程内存数据库KeyDB实战指南下一篇Claude Ads 付费媒体规划指南从广告策略蓝图到可执行的媒体计划创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表