Sdílet prostřednictvím


Modul runtime AddressSanitizer

Knihovna modulu runtime AddressSanitizer zachycuje běžné funkce a operace přidělování paměti, které umožňují kontrolu přístupu k paměti. Existuje několik různých knihoven modulu runtime, které podporují různé typy spustitelných souborů, které může kompilátor vygenerovat. Kompilátor a linker automaticky propojí příslušné knihovny modulu runtime, pokud předáte /fsanitize=address možnost v době kompilace. Výchozí chování můžete přepsat pomocí /NODEFAULTLIB možnosti v době propojení. Další informace najdete v části o propojení v jazyce AddressSanitizer, sestavení a ladění reference.

Při kompilaci cl /fsanitize=addresspomocí kompilátoru generuje instrukce pro správu a kontrolu stínových bajtů. Váš program používá tuto instrumentaci ke kontrole přístupu k paměti v zásobníku, v haldě nebo v globálním oboru. Kompilátor také vytváří metadata popisující zásobník a globální proměnné. Tato metadata umožňují modulu runtime generovat přesnou diagnostiku chyb: názvy funkcí, řádky a sloupce ve zdrojovém kódu. V kombinaci může kompilátor kontrolovat a knihovny modulu runtime přesně diagnostikovat mnoho typů chyb zabezpečení paměti, pokud jsou zjištěny za běhu.

Seznam knihoven modulu runtime pro propojení s modulem runtime AddressSanitizer od sady Visual Studio 17.7 Preview 3 následuje. Další informace o možnostech /MT (staticky propojit modul runtime) a /MD (dynamicky propojit redist při běhu) najdete v tématu /MD, /MT, /LD (použití knihovny runtime).

Poznámka:

V následující tabulce {arch} je buď i386 nebo x86_64. Tyto knihovny používají konvence jazyka Clang pro názvy architektur. Konvence MSVC jsou obvykle x86 a x64 nikoli i386 a x86_64, ale odkazují na stejné architektury.

Možnost CRT Knihovna modulu runtime AddressSanitizer (.lib) Binární soubor modulu runtime adresy (.dll)
/MT nebo /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD nebo /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

Následující diagram znázorňuje, jak jsou knihovny modulu runtime jazyka propojené pro /MTmožnosti , /MTd/MDa /MDd kompilátoru:

Diagram propojení knihoven modulu runtime pro různé možnosti kompilátoru

Na obrázku jsou tři scénáře propojení knihovny modulu runtime. První je /MT nebo /MTd. My_exe.exe i my_dll.dll se zobrazují s vlastními kopiemi staticky propojených modulů VCRuntime, Universal CRT a C++. Scénáře ukazují /MD, ve kterých my_exe.exe i my_dll.dll sdílejí vcruntime140.dll, ucrtbase.dll a msvcp140.dll. Poslední scénář ukazuje /MDd, ve kterém my_exe.exe i my_dll.dll sdílejí ladicí verze modulů runtime: vcruntime140d.dll, ucrtbased.dll a msvcp140d.dll

Následující diagram znázorňuje, jak je knihovna ASan propojená pro různé možnosti kompilátoru:

Diagram propojení knihovny DLL modulu runtime ASan

Na obrázku jsou čtyři scénáře pro propojení knihovny modulu runtime ASan. Scénáře jsou pro /MT (staticky propojit modul runtime), /MTd (staticky propojit ladicí modul runtime), /MD (dynamicky propojit redist za běhu), /MDd (dynamicky propojit ladicí redist za běhu). Ve všech případech my_exe.exe propojení a jeho přidružení my_dll.dll propojení s jednou instancí clang-rt.asan-dynamix-x86_64.dll.

I když se staticky propojí, musí být knihovna DLL modulu runtime ASan přítomna na rozdíl od ostatních komponent modulu runtime jazyka C.

Předchozí verze

Před sestaveními sady Visual Studio 17.7 Preview 3, které staticky propojené (/MT nebo /MTd) nepoužívají závislost knihovny DLL. Místo toho byl modul runtime AddressSanitizer staticky propojený s exe uživatele. Projekty DLL by pak načetly exporty z exe uživatele pro přístup k funkcím ASan.

Dynamicky propojené projekty (/MD nebo /MDd) používaly různé knihovny a knihovny DLL v závislosti na tom, jestli byl projekt nakonfigurován pro ladění nebo vydání. Další informace o těchto změnách a jejich motivaci naleznete v tématu MSVC Address Sanitizer – One DLL pro všechny konfigurace modulu runtime.

Následující tabulka popisuje předchozí chování propojení knihovny modulu runtime AddressSanitizer před sadou Visual Studio 17.7 Preview 3:

Možnost CRT KNIHOVNA DLL nebo EXE LADICÍ? Knihovna ASan (.lib) Binární soubor modulu runtime ASan (.dll)
/MT EXE No clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} Nic
/MT DLL No clang_rt.asan_dll_thunk-{arch} Nic
/MD kterýkoli No clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE Ano clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} Nic
/MT DLL Ano clang_rt.asan_dbg_dll_thunk-{arch} Nic
/MD Kteroukoli Ano clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

Následující diagram ukazuje, jak byla knihovna ASan propojena pro různé možnosti kompilátoru před sadou Visual Studio 2022 17.7 Preview 3:

Diagram propojení knihovny DLL modulu runtime ASan před sadou Visual Studio 2022 Preview 3

Na obrázku jsou čtyři scénáře pro propojení knihovny modulu runtime ASan. Scénáře jsou pro /MT (staticky propojit modul runtime), /MTd (staticky propojit ladicí modul runtime), /MD (dynamicky propojit redist za běhu), /MDd (dynamicky propojit ladicí redist za běhu). Pro /MT má my_exe.exe staticky propojenou kopii modulu runtime ASan. my_dll.dll odkazy na modul runtime ASan v my_exe.exe. V případě /MTd je diagram stejný s tím rozdílem, že používá staticky propojený modul runtime ASan s laděním. V případě /MD my_exe.exe i my_dll.dll propojení s dynamicky propojeným modulem runtime ASan s názvem clang_rt.asan_dynamic-x86_64.dll. V případě /MDd je diagram stejný s výjimkou my_exe.exe a my_dll.dll odkazu na ladicí modul runtime ASan s názvem clang_rt.asan_dbg_dynamic-x86_64.dll.

Průsečík funkce

AddressSanitizer dosahuje zachycení funkce prostřednictvím mnoha technik horkého opravy. Tyto techniky jsou nejlépe zdokumentované v samotném zdrojovém kódu.

Knihovny modulu runtime zachycuje mnoho běžných funkcí správy paměti a manipulace s pamětí. Seznam naleznete v tématu AddressSanitizer seznam zachycených funkcí. Průsečíky přidělení spravují metadata a stínové bajty související s každým voláním přidělení. Při každém zavolání funkce malloc delete CRT nastaví průsečíky konkrétní hodnoty v oblasti stínové paměti AddressSanitizer tak, aby označily, jestli jsou tato umístění haldy aktuálně přístupná a jaká jsou hranice přidělení. Tyto stínové bajty umožňují kompilátoru vygenerované kontroly stínových bajtů určit, zda je zatížení nebo úložiště platné.

Průsečík není zaručen, že bude úspěšný. Pokud je prologue funkce příliš krátká pro jmp zápis, může průsečík selhat. Pokud dojde k selhání zachycení, program vyvolá debugbreak a zastaví. Pokud připojíte ladicí program, vymaže příčinu problému se zachycením. Pokud máte tento problém, nahlaste chybu.

Poznámka:

Uživatelé se můžou volitelně pokusit pokračovat po neúspěšném průsečíku nastavením proměnné ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE prostředí na libovolnou hodnotu. Pokračování po selhání průsečíku může vést k chybějícím zprávám o chybách pro tuto funkci.

Vlastní alokátory a modul runtime AddressSanitizer

Modul runtime AddressSanitizer poskytuje průsečíky pro běžná rozhraní alokátoru , malloc/free,delete/HeapFree/HeapAllocnew (prostřednictvím ).RtlAllocateHeap/RtlFreeHeap Mnoho programů využívá vlastní alokátory z jednoho nebo jiného důvodu, příkladem by byl jakýkoli program používající dlmalloc nebo řešení využívající std::allocator rozhraní a VirtualAlloc(). Kompilátor nemůže automaticky přidávat volání správy stínové paměti do vlastního alokátoru. Je zodpovědností uživatele používat poskytnuté rozhraní ruční otravy. Toto rozhraní API umožňuje, aby tyto alokátory fungovaly správně s existujícími konvencemi runtime AddressSanitizer a stínových bajtů .

Ruční rozhraní otravy AddressSanitizer

Rozhraní pro enlightening je jednoduché, ale ukládá omezení zarovnání pro uživatele. Uživatelé mohou importovat tyto prototypy importem sanitizer/asan_interface.h. Tady jsou prototypy funkcí rozhraní:

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

Pro usnadnění je soubor hlavičky rozhraní AddressSanitizer k dispozici obálková makra. Tato makra kontrolují, jestli je během kompilace povolená funkce AddressSanitizer. Umožňují vašemu zdrojovému kódu vynechat volání funkce otravy, když nejsou potřeba. Tato makra by měla být upřednostňovaná před přímým voláním výše uvedených funkcí:

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

Požadavky na zarovnání pro otravu AddressSanitizer

Jakákoli ruční otrava stínových bajtů musí zvážit požadavky na zarovnání. Uživatel musí v případě potřeby přidat odsazení, aby stínové bajty skončily na hranici bajtů ve stínové paměti. Každý bit ve stínové paměti AddressSanitizer kóduje stav jednoho bajtu v paměti aplikace. Toto kódování znamená, že celková velikost každého přidělení, včetně jakéhokoli odsazení, musí odpovídat hranici 8 bajtů. Pokud požadavek na zarovnání není splněný, může to vést k nesprávnému hlášení chyb. Nesprávné hlášení se může projevit jako chybějící sestavy (falešně negativní) nebo zprávy o ne chybách (falešně pozitivní).

Obrázek požadavku na zarovnání a potenciálních problémů najdete v zadaných příkladech zarovnání ASan. Jeden je malý program, který ukazuje, co se může pokazit při ruční otravě stínové paměti. Druhým je příklad implementace ruční otravy pomocí std::allocator rozhraní.

Možnosti za běhu

Microsoft C/C++ (MSVC) používá modul runtime založený na modulu runtime Clang AddressSanitizer z úložiště projektu llvm. Z tohoto důvodu se mezi těmito dvěma verzemi sdílí většina možností modulu runtime. Tady je k dispozici úplný seznam veřejných možností modulu runtime Clang. Zdokumentujeme některé rozdíly v následujících částech. Pokud zjistíte možnosti, které nefungují podle očekávání, nahlaste chybu.

Nepodporované možnosti AddressSanitizer

  • detect_container_overflow
  • unmap_shadow_on_exit

Poznámka:

Možnost halt_on_error modulu runtime AddressSanitizer nefunguje očekávaným způsobem. V knihovnách modulu runtime Clang i MSVC se mnoho typů chyb považuje za nedostupné, včetně většiny chyb poškození paměti.

Další informace najdete v části Rozdíly v jazyce Clang 12.0 .

Možnosti modulu runtime specifické pro MSVC

  • windows_hook_legacy_allocators Logická hodnota, nastavená na false zakázání zachytávání GlobalAlloc a LocalAlloc alokátorů.

    Poznámka:

    Možnost windows_hook_legacy_allocators nebyla k dispozici ve veřejném modulu runtime llvm-project při psaní tohoto článku. Možnost může být nakonec přidána zpět k veřejnému projektu; ale závisí na kontrole kódu a přijetí komunity.

    Možnost windows_hook_rtl_allocators, dříve opt-in funkce, zatímco AddressSanitizer byl experimentální, je nyní povolena ve výchozím nastavení. Ve verzích před sadou Visual Studio 2022 verze 17.4.6 je falsevýchozí hodnota možnosti . V sadě Visual Studio 2022 verze 17.4.6 a novějších verzích je truevýchozí možnost windows_hook_rtl_allocators .

  • iat_overwrite Řetězec nastavený na "error" výchozí hodnotu. Další možné hodnoty jsou "protect" a "ignore". Některé moduly můžou přepsat import address table ostatní moduly a přizpůsobit implementace určitých funkcí. Například ovladače běžně poskytují vlastní implementace pro konkrétní hardware. Tato iat_overwrite možnost spravuje ochranu modulu runtime AddressSanitizer proti přepsání konkrétních memoryapi.h funkcí. Modul runtime v současné době sleduje VirtualAlloc, VirtualProtecta VirtualQuery funkce pro ochranu. Tato možnost je dostupná v sadě Visual Studio 2022 verze 17.5 Preview 1 a novějších verzích. iat_overwrite Následující hodnoty určují, jak modul runtime reaguje při přepsání chráněných funkcí:

    • Pokud je nastavená hodnota "error" (výchozí), modul runtime hlásí chybu při zjištění přepsání.
    • Pokud je nastavená hodnota "protect", modul runtime se pokusí vyhnout použití přepsání definice a pokračuje. Původní definice funkce se v podstatě používá z modulu runtime, memoryapi aby nedocházelo k nekonečné rekurzi. Ostatní moduly v procesu stále používají přepsánou definici.
    • Pokud je nastavená hodnota "ignore", modul runtime se nepokusí opravit žádné přepsané funkce a pokračuje se spuštěním.
  • windows_fast_fail_on_error Logická hodnota (ve výchozím nastavení false) je nastavená tak, aby true se proces po vytištění chybové zprávy ukončil s __fastfail(71).

Poznámka:

Pokud je hodnota abort_on_error nastavena na hodnotu true, program v systému Windows skončí ukončením(3). Abychom nezměnili aktuální chování, rozhodli jsme se místo toho zavést tuto novou možnost. Pokud jsou abort_on_error i windows_fast_fail_on_error pravdivé, program ukončí __fastfail.

AddressSanitizer list of intercepted functions (Windows)

Modul runtime AddressSanitizer za běhu provádí řadu funkcí, které umožňují kontroly bezpečnosti paměti za běhu. Tady je seznam funkcí, které modul runtime AddressSanitizer monitoruje, není vyčerpávající.

Výchozí průsečíky

Volitelné průsečíky

Průsečíky uvedené zde jsou nainstalovány pouze v případě, že je povolena možnost modulu runtime AddressSanitizer. Nastavte windows_hook_legacy_allocators na zakázání false starších zachytávání alokátoru. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

Viz také

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