ABV.GENERAL.MULTIDIMENSION
缓冲区溢出 — 数组索引超出边界
缓冲区溢出或溢出是一种异常现象,其中将数据写入缓冲区的程序会溢出缓冲区的边界并覆盖相邻的内存。通常,当一个程序将字符串复制到缓冲区时,便会发生这种问题。
C 和 C++ 不提供任何内置保护功能来阻止访问或覆盖内存任何部分中的数据,也不自动检查写入某一数组(此语言的内置缓冲区类型)的数据是否在该数组的边界内。
ABV.GENERAL.MULTIDIMENSION 检查器是一种通用检查器,用于查找多维数组(二维到 N 维数组)的数组边界违规情况,即对超出该数组边界的数组元素的任何访问。
漏洞与风险
旨在执行代码或改变程序操作方式的输入可触发缓冲区溢出。这可能导致程序行为不稳定,包括内存访问错误、错误的结果、故障或系统安全漏洞。
缓冲区溢出的后果包括有效数据被覆盖以及执行任意和潜在恶意代码。例如,缓冲区溢出可通过以下三种方式操纵程序:
- 覆盖内存中缓冲区附近的局部变量,以更改程序的行为使之有利于攻击者
- 覆盖堆栈帧中的返回地址,以便在攻击者指定的返回地址(通常为用户输入填充的缓冲区)处恢复执行
- 覆盖随后将执行的函数指针或异常处理程序
漏洞代码示例 1
复制
#include<iostream>
using namespace std;
int main()
{
// an array with 3 rows and 2 columns.
int x[3][2] = {0,1,2,3,4,5};
int *p = &x[0][0];
cout<<"Array access: "<<*(p+9)<<endl;
return 0;
}
Klocwork 针对第 10 行生成缓冲区溢出报告,指出多维数组 x 超出边界。
修正代码示例 1
复制
#include<iostream>
using namespace std;
int main()
{
// an array with 3 rows and 2 columns.
int x[3][2] = {0,1,2,3,4,5};
int *p = &x[0][0];
cout<<"Array access: "<<*(p+2)<<endl;
return 0;
}
在修正代码示例中,多维数组在索引范围内得到访问。
相关检查器
- ABV.ANY_SIZE_ARRAY
- ABV.GENERAL
- ABV.ITERATOR
- ABV.MEMBER
- ABV.STACK
- ABV.TAINTED
- ABV.UNICODE.BOUND_MAP
- ABV.UNICODE.FAILED_MAP
- ABV.UNICODE.NNTS_MAP
- ABV.UNICODE.SELF_MAP
- ABV.UNKNOWN_SIZE
外部指导
- CERT ARR00-C:了解数组的工作原理
- CERT ARR30-C:不形成或使用超出边界的指针或数组下标
- CERT ARR38-C:保证库函数不形成无效指针
- CERT CTR50-CPP:保证容器索引和迭代器在有效范围内
- CERT ENV01-C:不作出关于环境变量大小的假设
- CERT EXP08-C:确保指针算术运算使用正确
- CERT POS30-C:适当使用 readlink() 函数
- CWE-119:未正确地将操作限制在内存缓冲区边界内
- CWE-120:复制缓冲区而不检查输入大小(“典型的缓冲区溢出”)
- CWE-122:基于堆的缓冲区溢出
- CWE-124:缓冲区欠载(“缓冲区下溢”)
- CWE-125:超出边界的读取
- CWE-127:缓冲区读取不足
- CWE-193:差一错误
- CWE-251:无
- CWE-786:访问缓冲区开始之前的内存位置
- CWE-787:超出边界的写入
- CWE-788:访问缓冲区末尾之后的内存位置
- CWE-805:访问长度值错误的缓冲区
- CWE-806:使用源缓冲区的大小访问缓冲区
扩展
此检查器可通过 Klocwork 知识库进行扩展。有关详情,请参阅调整 C/C++ 分析。