3.1 sprintf函数引起的缓冲区溢出

3.1 sprintf函数引起的缓冲区溢出

2013-11-28 15:14 刘新浙/刘玲/王超/李敬娜 等 人民邮电出版社  字号: T |  T
一键收藏,随时查看,分享好友!

《从缺陷中学习C/C++》第3章库函数问题,本章主要介绍库函数的使用中会遇到的问题。使用库函数可以降低软件开发的难度,提高代码编写的效率。本节为大家介绍sprintf函数引起的缓冲区溢出。

AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验

第3章  库函数问题

本章主要介绍库函数的使用中会遇到的问题。使用库函数可以降低软件开发的难度,提高代码编写的效率。这一章主要涵盖的内容有,调用字符串库函数时需要注意对字符串结束符'\0'的处理,复制字符串的时候要注意内存空间是否写溢出,函数调用前需要做必要的初始化,函数使用后对其返回值需要做正确处理,容器类的增、删操作要注意迭代器失效等,忽视这些方面将带来各种各样的问题。

3.1  sprintf函数引起的缓冲区溢出

代码示例

   
   
  1. int main()  
  2. {  
  3.     char src[50] = "abcdefghijklmnopqrstuvwxyz";  
  4.     char buf[10] = "";  
  5.     int len = sprintf(buf, "%s", src);  
  6.     printf("src=%s\n", src);  
  7.     printf("len=%d\n", len);  
  8.     printf("buf=%s\n", buf);  
  9.     return 0;  
  10. }  

现象&后果

程序运行时,用sprintf函数把字符数组src的内容往字符数组buf复制时会溢出,可能出现段错误(Segmentation fault)。

Bug分析

上述代码从一个字符数组src复制字符串到另外一个字符数组buf中,src的字符串长度为26,但buf的长度只有10,用sprintf函数进行复制的时候会把src的所有字符往buf里写,从而引起buf溢出。

正确的做法是在复制之前检查buf的长度是否足够,或者直接用更安全的snprintf函数代替sprintf。

正确代码

   
   
  1. int main()  
  2. {  
  3.     char src[50] = "abcdefghijklmnopqrstuvwxyz";  
  4.     char buf[10] = "";  
  5.     int len = snprintf(buf, sizeof(buf), "%s", src);  
  6.     if(len > sizeof(buf) - 1)  
  7.     {  
  8.         printf("[Error] Source string length is %d. The buf size %d is not enough. Copy incomplete!\n", len, sizeof(buf));  
  9.     }  
  10.     else  
  11.     {  
  12.         printf("src=%s\n", src);  
  13.         printf("len=%d\n", len);  
  14.         printf("buf=%s\n", buf);  
  15.     }  
  16.     return 0;  
  17. }  

编程建议

在libc参考手册对sprintf函数的说明中有一个警告,如果复制的字符串长度超过提供的buf串的长度,sprintf函数会变得很危险。为了避免这个问题,可以用snprintf函数来代替sprintf函数。但在使用snprintf的时候,在调用这个函数之后需要对返回值作检查,如果返回值比分配的buf长度要大,表示复制不完整,则需要重新分配大的空间之后再一次调用snprintf函数。

在libc参考手册中,也同时提到,在实际使用过程中,用asprintf函数代替snprintf函数会更方便些。asprintf函数不需要预先分配buf,它能在复制过程中根据实际复制源字符串的大小动态分配空间,具体可参考libc参考手册。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值