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=address
pomocí 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 /MT
možnosti , /MTd
/MD
a /MDd
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:
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:
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
/HeapAlloc
new
(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á nafalse
zakázání zachytáváníGlobalAlloc
aLocalAlloc
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 jefalse
výchozí hodnota možnosti . V sadě Visual Studio 2022 verze 17.4.6 a novějších verzích jetrue
výchozí možnostwindows_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řepsatimport 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. Tatoiat_overwrite
možnost spravuje ochranu modulu runtime AddressSanitizer proti přepsání konkrétníchmemoryapi.h
funkcí. Modul runtime v současné době sledujeVirtualAlloc
,VirtualProtect
aVirtualQuery
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.
- Pokud je nastavená hodnota
windows_fast_fail_on_error
Logická hodnota (ve výchozím nastavení false) je nastavená tak, abytrue
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
__C_specific_handler
(pouze x64)_aligned_free
_aligned_malloc
_aligned_msize
_aligned_realloc
_calloc_base
_calloc_crt
_calloc_dbg
(pouze ladění modulu runtime)_except_handler3
(pouze x86)_except_handler4
(pouze x86) (nezdokumentováno)_expand
_expand_base
(nezdokumentováno)_expand_dbg
(pouze ladění modulu runtime)_free_base
(nezdokumentováno)_free_dbg
(pouze ladění modulu runtime)_malloc_base
(nezdokumentováno)_malloc_crt
(nezdokumentováno)_malloc_dbg
(pouze ladění modulu runtime)_msize
_msize_base
(nezdokumentováno)_msize_dbg
(pouze ladění modulu runtime)_realloc_base
(nezdokumentováno)_realloc_crt
(nezdokumentováno)_realloc_dbg
(pouze ladění modulu runtime)_recalloc
_recalloc_base
(nezdokumentováno)_recalloc_crt
(nezdokumentováno)_recalloc_dbg
(pouze ladění modulu runtime)_strdup
atoi
atol
calloc
CreateThread
free
frexp
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
RaiseException
realloc
RtlAllocateHeap
RtlCreateHeap
RtlDestroyHeap
RtlFreeHeap
RtlRaiseException
RtlReAllocateHeap
(nezdokumentováno)RtlSizeHeap
(nezdokumentováno)SetUnhandledExceptionFilter
strcat
strchr
strcmp
strcpy
strcspn
strdup
strlen
strncat
strncmp
strncpy
strnlen
strpbrk
strspn
strstr
strtok
strtol
wcslen
wcsnlen
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
GlobalAlloc
GlobalFree
GlobalHandle
GlobalLock
GlobalReAlloc
GlobalSize
GlobalUnlock
LocalAlloc
LocalFree
LocalHandle
LocalLock
LocalReAlloc
LocalSize
LocalUnlock
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