Sdílet prostřednictvím


Stínové bajty AddressSanitizer

Stručně shrneme koncept stínových bajtů a jejich použití implementací modulu runtime /fsanitize=address. Další podrobnosti najdete v počátečním výzkumu AddressSanitizer - Serebryany, et al a aktuální dokumentaci algoritmu AddressSanitizer.

Základní koncept

Každých 8 bajtů ve virtuálním adresním prostoru aplikace je možné popsat pomocí jednoho stínového bajtu.

Jeden stínový bajt popisuje, kolik bajtů je aktuálně dostupných takto:

  • 0 znamená všech 8 bajtů.
  • 1-7 znamená jeden až sedm bajtů.
  • Záporná čísla kódují kontext modulu runtime, který se má použít pro diagnostiku generování sestav.

Legenda stínového bajtu

Představte si tuto legendu stínového bajtu, kde jsou definována všechna záporná čísla:

Snímek obrazovky s legendou stínového bajtu AddressSanitizer

Mapování – popis adresního prostoru

Každých 8 bajtů ve virtuálním adresním prostoru aplikace, který je zarovnaný na 0-mod-8, je možné mapovat na stínový bajt, který popisuje tento slot ve virtuálním adresním prostoru. Toto mapování lze provést jednoduchým posunem a přidáním.

Na x86:

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

Na x64:

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

Generování kódu – testy

Zvažte, jak se můžou zapisovat konkrétní stínové bajty, a to buď kódem vygenerovaným kompilátorem, statickými daty nebo modulem runtime. Tento pseudokód ukazuje, jak je možné vygenerovat kontrolu, která předchází načtení nebo úložišti:

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

Při instrumentaci odkazu na paměť, který je menší než 8 bajtů široký, je instrumentace o něco složitější. Pokud je stínová hodnota kladná (což znamená, že k 8bavovým slovům je možné přistupovat pouze první k bajty), musíme porovnat posledních 3 bitů adresy s k.

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

Modul runtime i kód vygenerovaný kompilátorem zapisují stínové bajty. Tyto stínové bajty buď povolí nebo odvolá přístup, když se uvolní obory nebo úložiště. Výše uvedené kontroly čtou stínové bajty, které popisují 8bajtů "slotů" v adresním prostoru vaší aplikace v určitém okamžiku při provádění programu. Kromě těchto explicitně generovaných kontrol modul runtime také kontroluje stínové bajty po zachycení (nebo "háky") mnoho funkcí v CRT.

Další informace najdete v seznamu zachycených funkcí.

Nastavení stínových bajtů

Kód, který kompilátor vygeneruje, i modul runtime AddressSanitizer může zapisovat stínové bajty. Kompilátor může například nastavit stínové bajty, aby umožňoval pevný přístup k místním objektům zásobníku definovaným ve vnitřním oboru. Modul runtime může obklopovat globální proměnné v oddílu dat stínovými bajty.

Viz také

Přehled AddressSanitizer
Známé problémy s addressSanitizerem
Referenční dokumentace k sestavení a jazyku AddressSanitizer
Referenční informace k modulu runtime AddressSanitizer
AddressSanitizer – cloud nebo distribuované testování
Integrace ladicího programu AddressSanitizer
Příklady chyb AddressSanitizer