AddressSanitizer 陰影位元組

我們簡短摘要說明陰影位元組的概念,以及 執行時間實 /fsanitize=address 作如何使用它們。 如需進一步的詳細資料,請參閱 開創性論文 AddressSanitizer 演算法

核心概念

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

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

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

陰影位元組圖例

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

Screenshot of the AddressSanitizer shadow-byte legend.

對應 - 描述您的位址空間

應用程式虛擬位址空間中對齊 「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 錯誤範例