DBZ.ITERATOR.CALL

函数调用中可能出现除以零的情况

尝试在除法或模运算中使用零作为除数会导致运行时错误。错误处理或争用条件无效时,经常出现除以零的情况,并且通常会导致程序异常终止。在 C/C++ 代码中将值用作除法或模运算的除数之前,必须进行检查以确认值不为零。

DBZ 检查器会查找零常量值用作除法或模运算除数的实例。

DBZ.ITERATOR.CALL 检查器会标记调用函数时可能在除以零的运算中使用循环迭代器的情况。

漏洞与风险

通常需要小心避免出现除以零的情况,以防程序崩溃。如果函数由于调用方提供的除法器而有可能触发此问题,则函数用户可能导致除以零的情况。如果除法器条件由循环决定,这种情况尤其容易发生,因为更难进行计算或预期将会发生什么。

缓解与预防

异常处理无效时,经常出现除以零的情况。为避免此漏洞,在将值用作除法或模运算的除数之前,检查该值是否为零。

必须计算和设置除法器的范围,以免函数内部和函数调用方中出现零条件。

漏洞代码示例 1

复制
int foo(int a, int b)
{
    int x = 0;
    for (int i = a; i < b; i++) {
        x += 100/i;
    }
    return x;
}
void bar()
{
    int a = -3;
    int b = 2;
    foo(a, b);    // DBZ.ITERATOR.CALL
}

在函数 foo 中,for 循环条件由参数 a 和 b 决定。bar 函数使用参数 -3 和 2 调用 foo 函数,这个范围包括 0。Klocwork 在第 13 行报告 DBZ.ITERATOR.CALL 问题。

修正代码示例 1

复制
int foo(int a, int b)
{
    int x = 0;
    for (int i = a; i < b; i++) {
        x += 100/i;
    }
    return x;
}
void bar()
{
    int a = -3;
    int b = 0;
    foo(a, b);    // NO DBZ.ITERATOR.CALL
}

通过将函数栏中的变量 b 调整为 0,循环条件不再达到 0。

漏洞代码示例 2

复制
int foo(int a, int b)                                    
{                                                        
    int x = 0;                                           
    for (int i = a; i >= b; i--) {                        
        x += 100/i;                                      
    }                                                    
    return x;                                            
}                                                        
void bar()                                               
{                                                        
    foo(3,0);    // DBZ.ITERATOR.CALL                   
}

与示例 1 类似,函数 foo 包含一个 for 循环,但在本例中,循环条件包含 0 作为其最小值。因此,使用参数 0 调用 foo 会在第 11 行触发 DBZ.ITERATOR.CALL 问题。

修正代码示例 2

复制
int foo(int a, int b)                                    
{                                                        
    int x = 0;                                           
    for (int i = a; i >= b; i--) {                        
        x += 100/i;                                      
    }                                                    
    return x;                                            
}                                                        
void bar()                                               
{                                                        
    foo(3,1);    // NO DBZ.ITERATOR.CALL                   
}

在此修正示例中,调用方使用参数 3 和 1,因此避免了循环中出现 0 条件。

安全培训

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

扩展

此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。