AddressSanitizer 陰影位元組

我們簡短摘要說明陰影位元組的概念,以及運行時間實 /fsanitize=address作如何使用它們。 如需進一步的詳細數據,請參閱初始研究 AddressSanitizer - Serebryany 等和目前的 AddressSanitizer 演算法檔

核心概念

您可以使用一個陰影位元組來描述您應用程式虛擬位址空間中的每 8 個字節

一個陰影位元組描述目前可存取的位元組數目,如下所示:

  • 0 表示所有 8 個字節
  • 1-7 表示一到七個字節
  • 負數編碼運行時間用於報告診斷的內容。

陰影位元組圖例

請考慮定義所有負數的這個陰影位元組圖例:

AddressSanitizer 陰影位元組圖例的螢幕快照。

對應 ─ 描述您的地址空間

應用程式虛擬位址空間中對齊 「0-mod-8」 的每個 8 個字節,都可以對應至描述虛擬位址空間中該位置的陰影位元組。 此對應可以透過簡單的移位和新增來完成

在 x86 上:

char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)

在 x64 上:

char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)

程式代碼產生 - 測試

請考慮編譯程式產生的程式代碼、靜態數據或運行時間可能會寫入特定陰影位元組的方式。 此虛擬程式代碼示範如何產生任何負載或存放區前面的檢查:

ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
    ReportAndCrash(Addr);
}

檢測小於8個字節的記憶體參考時,檢測會稍微複雜一點。 如果陰影值是正數(這表示只能存取 8 位元元中的第一個 K 位元組),我們需要比較地址的最後 3 位與 k。

ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k)) {
    ReportAndCrash(Addr);
}

運行時間和編譯程式產生的程式代碼都會寫入陰影位元組。 當範圍結束或記憶體釋出時,這些陰影位元組會允許或撤銷存取權。 上述檢查會讀取陰影位元組,以描述應用程式地址空間中的8位元組「位置」,在程式執行的特定時間。 除了這些明確產生的檢查之外,運行時間也會在攔截CRT中的許多函式之後檢查陰影位元組。

如需詳細資訊,請參閱攔截的 式清單。

設定陰影位元組

編譯程式產生的程序代碼和 AddressSanitizer 運行時間都可以寫入陰影位元組。 例如,編譯程式可以設定陰影位元組,以允許固定大小的存取內部範圍中定義的堆疊局部變數。 運行時間可以使用陰影位元組括住數據區段中的全域變數。

另請參閱

AddressSanitizer 概觀
AddressSanitizer 已知問題
AddressSanitizer 組建和語言參考
AddressSanitizer 運行時間參考
AddressSanitizer 雲端或分散式測試
AddressSanitizer 調試程式整合
AddressSanitizer 錯誤範例