CodeQL 文档

指针溢出检查

ID: cpp/pointer-overflow-check
Kind: problem
Security severity: 2.1
Severity: error
Precision: high
Tags:
   - reliability
   - security
   - external/cwe/cwe-758
Query suites:
   - cpp-code-scanning.qls
   - cpp-security-extended.qls
   - cpp-security-and-quality.qls

单击查看 CodeQL 仓库中的查询

在检查整数溢出时,您通常会编写类似 p + i < p 的测试。如果 pi 是无符号整数,此方法有效,因为加法中的任何溢出都会导致值简单地“环绕”。但是,当 p 是指针时,使用此模式存在问题,因为根据 C 和 C++ 标准,指针溢出具有未定义的行为。如果加法溢出并产生未定义的结果,则比较也会是未定义的;它可能会产生意外的结果,或者可能会被优化编译器完全删除。

建议

要检查索引 i 是否小于数组的长度,只需将这两个数字作为无符号整数进行比较:i < ARRAY_LENGTH。如果数组的长度定义为两个指针 ptrp_end 之间的差值,则编写 i < p_end - ptr。如果 i 是有符号的,则将其强制转换为无符号,以防出现负数 i。例如,编写 (size_t)i < p_end - ptr

示例

最常见的一种无效的指针溢出检查方法是检查数字 a 是否过大,首先检查将该数字添加到 ptr 是否超过分配的末尾,然后检查将其添加到 ptr 是否会创建一个指针,该指针过大以至于溢出并环绕。

bool not_in_range(T *ptr, T *ptr_end, size_t i) {
    return ptr + i >= ptr_end || ptr + i < ptr; // BAD
}

在这两种检查中,操作的顺序都错误。首先,评估可能会导致未定义行为的表达式(ptr + i),然后检查结果是否在范围内。但是,一旦在指针加法中发生了未定义的行为,就无法恢复:在可能的指针溢出之后执行范围检查已经太迟了。

虽然这不是本查询的主题,但表达式 ptr + i < ptr_end 也是一个无效的范围检查。在 C/C++ 中,创建指向分配末尾的最后一个位置之后的指针是未定义的行为。

下一个示例展示了如何以可移植的方式检查无符号数字是否超出 ptrptr_end 之间分配的范围。

bool not_in_range(T *ptr, T *ptr_end, size_t i) {
    return i >= ptr_end - ptr; // GOOD
}

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私