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參考手冊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章