什么是缓冲区溢出?
copy数据进buffer时,数据长度超过buffer中的剩余空间。
缓冲区溢出的危害?
缓冲区溢出,结果随机,可能会导致程序功能不正常,也可能导致程序崩溃。如果受到影响的是其它功能,因为故障现象随机,所以问题通常很难定位。别有用心的攻击者还会利用缓冲区溢出缺陷,覆盖控制变量的内容,接管程序的运行。
详细来说:
读越界时,因为读取到错误的数据,所以可能导致功能不正常,也可能导致程序崩溃。写越界时,如果后面的内存存放着应用程序的数据,则会导致其它功能读取到错误的数据,其它功能因此工作不正常,也可能导致程序崩溃。写越界时,如果后面的内存被用于程序运行的控制,则影响程序的运行,别有用心的黑客可以利用这一点实现程序的接管。写越界时,如果后面的内存没有在使用,则没有明显影响。
如何防止缓冲区溢出?
不能使用strcpy()、sprintf()等不安全的函数,而要在strncpy()、memcpy()、snprinf()的基础上封装出安全的函数,对copy进buffer的内容大小进行限制,超过大小则截断。
在strncat的基础上封装安全的函数:
char *strncat_s(char *dest, const char *src, size_t n,size_t total_buf_size){
/*如果buffer溢出,则截断,copy满为止,减1是为了存放字符串结束标志*/
if(strlen(dest)+n>total_buf_size-1){
n=total_buf_size-1-strlen(dest);
}
return strncat(dest, src, n);
}
类似的,在memcpy基础上封装安全的函数:
void *memcpy_s(void *dest, const void *src, size_t n, size_t left_buf_size){
/*如果buffer溢出,则截断,copy满为止*/
if(n> left_buf_size){
n= left_buf_size;
}
return memcpy (dest, src, n);
}
注意:我们通常不会记录buffer还剩余多少字节的空间,但是我们知道buffer的总大小和已经使用的大小,前者-后者就得到了剩余空间。
除非是性能要求非常高的地方,否则使用安全函数。比如多核CPU路由器转发平面C代码,性能要求很高,逻辑是一条线,非常清晰可控,所以不需要使用安全函数。路由器控制平面代码功能复杂,buffer溢出的可能性很难杜绝,性能要求相对较低,所以都使用安全函数。
读buffer时如果指针偏移量+要读的字段大小>buffer总大小,则会发生读溢出,但是这种溢出相比于写溢出好定位很多。因为读buffer的功能会失效。所以代码中不需要再做额外的安全性检查。