NUM.OVERFLOW

错误类型转换导致的数值溢出

如果变量进行了错误的类型转换,则 NUM.OVERFLOW 检查器将检测溢出事件。

漏洞与风险

因错误的类型转换导而致的数值溢出可能会造成结果错误。即使通过调试也很难对此进行追踪;主要是因为错误结果通常会显示为较大表达式中的子表达式,且其生成的溢出值处理起来比较棘手。要防止出现此类问题,需要对运算符优先权进行检查并小心地将其应用于复杂表达式。检查器仅在错误执行显式类型转换时启动。

漏洞代码示例

复制
  typedef unsigned long long uint64_t;
  typedef unsigned int uint32_t;
  uint64_t foo(uint32_t x, uint32_t y) {
    uint64_t z;
    z = (uint64_t) ( x * y );
    z = (uint64_t) ( y * 1000000U );
    return z;
  }

在上面的示例的第 5 和 6 行中,开发人员预期乘法运算的结果会占用 64 位,即使操作数均为 32 位时亦是如此。两行均存在错误的类型转换;由于乘法将先在 32 位中执行(导致溢出),之后进行向上转换。Klocwork 会在第 5 和 6 行生成 NUM.OVERFLOW

修正代码示例 1

复制
  typedef unsigned long long uint64_t;
  typedef unsigned int uint32_t;
  uint64_t foo(uint32_t x, uint32_t y) {
    uint64_t z;
    z = (uint64_t) ( x ) * y;
    z = (uint64_t) ( y ) * 1000000U; //or: y*1000000ULL
    return z;
  }

在第 5 行中,变量 x 首先进行向上转换。这将造成 y 自动提升,并导致完整的 64 位乘法。如果使用常量(位于第 6 行),则适当地利用后缀(在此情况中为 ULL)将告知编译器也提升 y。

漏洞代码示例 2

复制
  typedef unsigned long long uint64_t;
  typedef unsigned int uint32_t;
  uint32_t get_val();
  uint64_t foo(uint32_t x, uint32_t y) {
    uint64_t z;
    z = (uint64_t) ( y * get_val() );
    return z;
  }

上述示例的第 6 行上显示了类似问题,但是此次使用函数调用。

修正代码示例 2

复制
  typedef unsigned long long uint64_t;
  typedef unsigned int uint32_t;
  uint32_t get_val();
  uint64_t foo(uint32_t x, uint32_t y) {
    uint64_t z;
    z = (uint64_t) ( y ) * get_val();
    return z;
  }

安全培训

应用程序安全培训材料由 Secure Code Warrior 提供。

扩展

此检查器无法进行扩展。