官术网_书友最值得收藏!

2.6.4 Visual Studio中編譯器生成的運行時檢查

微軟的Visual Studio C++編譯器提供了幾個選項來在運行時啟用特定的檢查。這些選項可以使用特定的編譯器標志來啟用。尤其是,/RTCs編譯器標志打開了以下錯誤檢查:

·局部變量溢出,如數(shù)組(除了在一個內部填充的結構中使用時)

·使用未初始化的變量

·棧指針損壞,這可能是由于調用約定不匹配造成的

這些標志可以在代碼的各區(qū)域中調整或關閉。例如,下面的編譯指示:

#pragma runtime_checks("s", off)

對代碼中的任何后續(xù)函數(shù)關閉/RTCs標志檢查。這個檢查可以用如下編譯指示恢復:

#pragma runtime_checks("s", restore)

運行時邊界檢查。雖然未向公眾公開,但一些現(xiàn)有的C語言編譯器和運行時系統(tǒng)確實執(zhí)行數(shù)組邊界檢查。

Libsafe和Libverify。Libsafe是Avaya Labs Research 提供的一個動態(tài)庫,它能限制棧的緩沖區(qū)溢出的影響。這個庫可以攔截容易產生緩沖區(qū)溢出的C庫函數(shù)并檢查其參數(shù)范圍。這個庫確保幀指針和返回地址不能被攔截函數(shù)覆蓋。同樣也是由Baratloo和同事提供的[Baratloo 2000]Libverify庫則實現(xiàn)了與Libsafe 類似的返回地址驗證方案,但不需要重新編譯源代碼,這使得它能夠用于現(xiàn)有的二進制程序文件。

CRED。Richard Jones和Paul Kelley[Jones 1997]提出了一個利用引用對象進行邊界檢測的方法。這種方法基于以下原則:一個根據(jù)邊界內指針計算出來的地址必定與原始指針指向相同的對象。遺憾的是,數(shù)目驚人的現(xiàn)有程序生成并存儲邊界外地址,然后在計算中又取得這些地址處的值,而這些操作并未造成緩沖區(qū)溢出,這就使得這些程序不適宜采用前述的邊界檢測方式。這種運行時邊界檢查方式還要付出顯著的性能代價,尤其在某些指針密集型的程序中,性能下降可達30倍之多[Cowan 2000]。

Olatunji Ruwase和Monica Lam[Ruwase 2004]在他們的C范圍錯誤偵測器(C Range Error Detector,CRED)中改進了Jones和Kelley的方法。根據(jù)作者的說法,CRED執(zhí)行一種寬松的正確性標準,這是通過允許程序操作不會引起緩沖區(qū)溢出的邊界外地址而做到的。這個寬松的正確性標準為現(xiàn)有的軟件提供了較高的兼容性。

CRED可以被配置為檢測所有數(shù)據(jù)的邊界或者僅檢測字符串數(shù)據(jù)的邊界。完全邊界檢測,比如Jones和Kelley的方法,會產生顯著的性能開銷。將對邊界的檢查局限于字符串可改善大多數(shù)程序的性能。視應用程序中對字符串的使用情況,這種性能的開銷范圍為1%~130%。

邊界檢測可以有效地阻止大多數(shù)溢出情況,但這種方式并非完美。以CRED方案為例,它無法檢測出一個邊界外指針首先利用算術操作強制轉換為整數(shù)然后強制轉換回指針的情況。這種方案確實可以防止棧、堆和數(shù)據(jù)段的溢出。甚至當優(yōu)化到僅檢測字符串溢出的情況時,CRED也可以有效地檢測出由John Wilander和Marian Kamkar開發(fā)的用于評估動態(tài)緩沖區(qū)溢出檢測器的20種不同的緩沖區(qū)溢出攻擊[Wilander 2003]。

CRED已經合并到最新的(針對GCC 3.3.1的)Jones和Kelley檢測器中,此檢測器目前由Herman ten Brugge維護。

Dinakar Dhurjati和Vikram Adve提出了一個改進的集合,包括池分配,這使得編譯器生成在運行時在對象表中搜索對象的代碼[Dhurjati 2006]。這個改進的性能有顯著提高,但開銷仍高達69%。

主站蜘蛛池模板: 扶绥县| 兴化市| 鱼台县| 航空| 勃利县| 朝阳县| 北票市| 万山特区| 保康县| 彭阳县| 仙桃市| 渭源县| 双鸭山市| 荥阳市| 舞钢市| 丁青县| 永年县| 龙江县| 南平市| 武胜县| 溧水县| 苍梧县| 湄潭县| 文安县| 日照市| 周至县| 清水县| 宁强县| 腾冲县| 军事| 碌曲县| 兖州市| 拉萨市| 南平市| 郎溪县| 天镇县| 台北市| 古交市| 阿克| 桐梓县| 河间市|