2008-10-03 22 views
16

我被要求維護一個充滿內存泄漏的大型C++代碼庫。當我發現,我發現我們有很多導致泄漏的緩衝區溢出(這是怎麼回事,我從不想知道)。什麼C/C++函數最常被錯誤地使用,並可能導致緩衝區溢出?

我決定首先刪除緩衝區溢出,從危險函數開始。哪些C/C++函數最常使用不正確,並可能導致緩衝區溢出?

對於用於幫助尋找緩衝區溢出,我已經created another question that deals with this

+0

我不明白這個問題。如果小心處理,這裏沒有任何功能會導致溢出。 – unexist 2008-10-03 14:43:43

+2

@unexist:如果使用正確,沒有任何功能會出錯。問題是哪些函數經常被錯誤地使用,並導致可能導致緩衝區溢出。 – 2008-10-03 14:50:58

+0

你在使用什麼編譯器/平臺?有很多工具可以自動找到這類東西。 – twk 2008-10-03 15:49:14

回答

2

這裏編譯器和/或工具的一些功能,我發現是危險的:)

  • 得到( - 它不檢查變量的長度,如果輸入大於變量的緩衝區,可以覆蓋內存。
  • scanf() - 我很高興Visual Studio告訴我這個函數已被棄用。這是一個簡單的修復。
  • strcpy() - 如果源的內存空間大於目標的內存空間,則目標之後的數據將被覆蓋。
2

不幸的是任何陣列可導致緩衝區溢出:

uint32_t foo[3]; 
foo[3] = WALKED_OFF_END_OF_ARRAY; 

在功能方面,sprintf的將愉快地走下緩衝器的末端。它可以被snprintf取代。

11

通常,任何不檢查參數範圍的函數。名單將

  • 得到()
  • 的scanf()
  • 的strcpy()
  • 的strcat()

您應該使用尺寸限制的版本一樣stncpy,strncat函數,與fgets,等等。然後在給出尺寸限制時要小心;考慮終止字符串的'\ 0'。

此外,數組不是在C或C++中檢查。以下示例會導致錯誤。見off by one error

int foo[3]; 
foo[3] = WALKED_OFF_END_OF_ARRAY; 

編輯:@MrValdez的複製答案,@Denton金特里

0

基本上,任何事情接受一個指針和寫它,沒有檢查長度。所以像strcpy(),sprintf()等東西。

2

Memcpy()是另一個危險的。

訪問數組的任何循環都是一個危險點,因爲沒有停止超出數組的末尾。

內存泄漏是由分配內存引起的,沒有釋放內存。構造函數和析構函數應該是另一個強大的審查點,後者確保任何分配的內存都是空閒的。

2

您使用的是哪個版本的visual studio?在2008年啓用所有警告後,您提到的所有功能(以及更多)都會警告您已棄用它們。

也許你可以檢查所有的警告是否已打開,並讓編譯器爲你做好工作?

作爲一個便箋,優秀的writing secure code做了很好的工作,解釋了一些舊功能的不同之處。

2

我在工作的代碼庫上遇到了相同的問題。我的建議是:小心任何看起來像str *()和mem *()的C函數。也要小心任何需要指針指向緩衝區的東西,而且不會有長度。由於看起來你有機會使用C++,所以我會在最極端的情況下嘗試使用C++容器來處理事物:矢量,字符串,映射等等。這些讓你的生活變得更容易。

此外,自動化問題檢測工具也非常棒。如果你可以使用valgrind,我會推薦它。 Rational Purify也是非常強大的,雖然不便宜。

3

問題是從錯誤的結局開始,恐怕。假設緩衝區溢出發生在其他功能中。根據我的經驗,最常見的原因是operator ++,或者缺少操作符!=。

在Visual Studio 2005/8中找到一批的最佳解決方案是/ GS。它不會找到所有這些,但它是減少所需手動工作量的便宜方法。

5

Valgrind是你最好的朋友。

的valgrind --tool = MEMCHECK --leak校驗=全./a.out

1

在下另外疑難雜症是 「函數strncpy()」 函數。許多人沒有意識到它可以自由地返回一個非null結尾的字符串。