几十年以来,在<cstring>和<cstdio>里所声明的标准C函数已经由于缓冲区溢出的问题,成为错误和安全漏洞的沃土。尽管专家建议的解决办法是迁移到C++的<string>和<sstream>库,但是这并不总是可能的。
最近一项关于在很多流行的应用程序和操作系统里同安全相关的错误的研究表明,C-string函数所使用的范围要比我们想像的大得多。下面的提示会告诉你可以如何轻易地提高代码的安全系数,即使它使用的是标准的C函数。
C99标准包括了新的函数,它们能够明确地检查缓冲区的大小,因此可以减少溢出的机会。想一想下面这个有问题的例子:
void f(const char *p) { char buf[11]={0}; sprintf(buf,"%10s",p); //very dangerous printf("%sn",buf); }
不要让格式标记"%10s"误导了你。如果p碰巧大于10个字符,那么sprintf()所写的内容就会超出buf的边界,从而导致缓冲区的溢出:
f("hello world!"); //12 characters + nul
检查出这样的问题并不容易,因为它们只会在p大于10个字符的时候发生。黑客们常常会寻找这样容易出错的代码,以闯入看上去很安全的系统。要解决这个问题,就要把sprintf()替换成snprintf(),这样就有了下面的内容:
int snprintf(char* buf, size_tmaxlen, const char* fmt, ...);
第二个自变量定义了写入到buf的字符的最大数量,而不管格式标记和源字符串的大小:
snprintf(buf, 10, "%10s",p); //now safe f("hello world!"); //string is chopped to "hello worl0"
类似的,你要分别使用strncpy()、strncmp()、strncat()、strnicmp()和strnset(),而不要使用strcpy()、strcmp()、strcat()、stricmp()和strset()。例如:
const int LINE_SIZE=81; char buf[LINE_SIZE]={0}; // write up to 80 chars to buf: strncpy(buf, dest, LINE_SIZE-1); // compare no more than 80 chars: int equal= strncmp(buf, dest, LINE_SIZE-1);
使用限制了缓冲区的C函数能够减少缓冲区溢出的可能性,而不需要改动很多的原始代码。
本文作者:Danny Kalev是系统分析师兼软件工程师,在C++和面向对象的设计上14年的专业经验。  
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
|