您的位置:首页 > 编程语言 > ASP

用 snprintf / asprintf 取代不安全的 sprintf

2015-07-18 16:37 726 查看
snprintf (或者_snprintf )可以用来只计算长度,如:int c = snprintf(NULL,0,......);

asprintf
第一个参数是指向指针的指针,它会在heap中自动申请空间(最后要手动free)。使用asprintf
,要加上 #define _GNU_SOURCE

在 C语言里,要建立一个字符数组的字符串,常常会使用
sprintf()
这个函数来做格式化的处理。但是实际上,这个函式却不是那么「安全」。怎么说呢?sprintf()
的整个界面长的样子的是:
int sprintf ( char * str, const char * format, ...)
函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。

函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。

也就是在使用前,必须要先建立好一个字符数组的空间,再用这个函式把内容填入,下面就是简单的例子:
int tmp = 10;

char cstr[20];

sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
在 这个例子里,cstr最后的值,会是「10 * 10 =100」,看起来好像很好?但是如果把 tmp 的值改成 10000 的话,cstr 则应该要变成「10000 * 10000 = 100000000」,但是由于这时候的字符串所需长度为26,而要写入的 cstr 的长度只有20,所以就会造成 buffer overflow 的问题。
像如果是以 Visual C++ 2006来编译的话,如果程序里有用到 sprintf(),他在编译时就会显示一个警告讯息:
warning C4996: 'sprintf': This function orvariable may be unsafe. Consider using sprintf_sinstead.
而要怎么避免 sprintf 的buffer overflow的问题呢?除了微软建议的 sprintf_s() 外,实际上在 C99 里, 也多了一个
snprinf() 是用来取代现有的sprintf()了~他的界面是:
int snprintf(char *str, size_t size, const char *restrict format, ...)
应该可以明显看得出来,snprinf() 这个函式比 sprintf() 多了一个参数
size;这个参数的用处,就是用来限制最大的写入数据量,可以用来避免bufferoverflow。以上面的例子来说,本来写:
int tmp = 10000;

char cstr[20];

sprintf( cstr, "%d * %d = %d", tmp, tmp, tmp * tmp );
的话,会产生 buffer overflow的问题。而如果改成用 snprinf() 的话,就是变成:
int tmp = 10000;

char cstr[20];

snprintf( cstr, sizeof( cstr ), "%d * %d = %d", tmp,tmp, tmp * tmp );
这样一来,snprinf()在把数据写到 cstr时,最多就只会写入20个字符(cstr的长度),而不会有 bufferoverflow 的问题了~
int asprintf(char **strp, const char *fmt,
...);

int vasprintf(char **strp, const char *fmt,
va_list
ap);
描述
函数 asprintf()和 vasprintf()是 sprintf(3)和 vsprintf(3)的对等物,除了它们分配一个包括结尾空字符在内的足够大的输出内存,并且通过其第一个参数返回。这个指针应该传给 free(3)以在不再使用时释放它。
返回值
当成功时,如同 sprintf(3)一样,这些函数返回打印的字节个数。如果内存分配失败,或者其它错误发生了,这些函数返回
-1,并且 strp 的内容是未定义的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: