避免缓冲区溢出
13.1 ID_bufferOverflow
“缓冲区(buffer)”的本意是指内存等高速设备上的区域,程序在这种区域内接收或处理数据,之后再一并输出到网络或磁盘等低速环境,起到提高效率的作用,故称缓冲区。连续的内存区域均可称为缓冲区,在 C/C++ 语言中对应数组等结构。
缓冲区之外可能是程序的其他数据,也可能是函数返回地址、资源分配信息等重要数据,对缓冲区的越界读写往往意味着逻辑错误,而且会使程序遭到破坏。
示例:
void foo(const char* s) {
char buf[100];
strcpy(buf, s); // Non-compliant
....
}
int main() {
foo(userInput());
}
例中 userInput 函数返回用户输入的字符串,其长度不确定,而缓冲区 buf 的长度为 100 字节,如果用户输入超过这个长度就会使程序遭到破坏,这种问题称为“缓冲区溢出(buffer overflow)”,也是程序遭受攻击的常见原因。
缓冲区溢出可造成严重危害,如:
- 破坏堆栈或段结构,扰乱程序执行
- 改写关键信息,篡改程序行为
- 注入并运行恶意代码
- 攻击高权限进程获取非法权限
所以将读写限定在缓冲区边界之内是十分重要的,示例代码应改为:
void foo(const char* s) {
char buf[100] = "";
strncpy(buf, s, sizeof(buf) - 1); // Compliant
....
}
strncpy 与 strcpy 不同,当源字符串长度超过指定限制时会结束复制,但要注意 strncpy 对空字符的处理。