用 snprintf / asprintf 取代不安全的 sprintf

snprintf (或者_snprintf )可以用来只计算长度,如:int c = snprintf(NULL,0,......);


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


C语言里,要建立一个字符数组的字符串,常常会使用 sprintf() 这个函数来做格式化的处理。但是实际上,这个函式却不是那么「安全」。怎么说呢?sprintf() 的整个界面长的样子的是:

int sprintf ( char * str, const char * format, ...)

函数说明:最多从源串中拷贝n1个字符到目标串中,然后再在后面加一个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 的内容是未定义的。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值