我正在撰寫一些可以在 Linux 機器和 Windows 機器上編譯的 C 代碼(具體來說,我正在撰寫在某些 R 函式中使用的 C 代碼,而不是獨立的 C 程式)。編譯此代碼時,我在我的 Linux 機器上得到“檢測到堆疊粉碎”,但是當我在 Windows 機器上編譯它時沒有拋出錯誤。我已經確定了錯誤發生的位置(寫入超出其長度的陣列),并修復了它,但現在我很好奇:
有人可以解釋為什么在 Windows 機器上編譯的 C 代碼(使用 R devtools 附帶的標準 C 編譯器)會允許堆疊粉碎不被注意,而我的 Linux 機器上的編譯器會出錯。只是編譯器設定的不同嗎?即使在 Windows 機器上也能得到一些保護不是更好嗎?我已經解決了這個問題,所以這個問題只是出于好奇!
uj5u.com熱心網友回復:
它是編譯器設定和兩個作業系統上為此目的使用的機制差異的組合。
在 Linux GCC/clang 上,您有“堆疊保護器”(-fstack-protector),而在 MSVC 上,您有“GuardStack”(/GS)。檢測堆疊緩沖區溢位的底層策略是相似的,但實作和二進制檢測機制不同。根據編譯器版本和設定,這些選項可能啟用或不啟用,并且可能只能在某些條件下而不是其他條件下檢測錯誤。
使用 R devtools 附帶的標準 C 編譯器
我不熟悉您使用的編譯器,但我會檢查它的配置以了解是否啟用了 GuardStack。
有人可以解釋為什么在 Windows 機器上編譯的 C 代碼(使用 R devtools 附帶的標準 C 編譯器)會允許堆疊粉碎不被注意,而我的 Linux 機器上的編譯器會出錯。
有兩種合理的解釋:
您沒有在 Windows 構建中啟用 GuardStack,而在您的 Linux 構建中,堆疊保護器默認啟用。
您啟用了 GuardStack,但系統無法在 Windows 上檢測到運行時堆疊粉碎,因為 (A) 它根本沒有發生(即對齊要求可能會生成一個比源代碼看起來更大的緩沖區,而您沒有超出其大小)或(B)它正在發生,但未被檢測到。例如,您可能會溢位緩沖區,但不足以破壞堆疊金絲雀值或保存的回傳地址,因此未被檢測到。
在任何情況下,要理解的關鍵點是兩者-fstack-protector并且/GS通常只檢測足夠大的緩沖區溢位,這些溢位超出了當前堆疊幀中的區域變數,并可能破壞保存的幀指標或回傳地址。它們不檢測任何型別的緩沖區溢位,也不執行嚴格的邊界檢查。您可以通過我上面提供的檔案鏈接了解有關何時/如何進行此檢測的更多資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/516464.html
