Sdílet prostřednictvím


Referenční informace k jazyku AddressSanitizer, sestavení a ladění

Části v tomto článku popisují specifikaci jazyka AddressSanitizer, možnosti kompilátoru a možnosti linkeru. Popisují také možnosti, které řídí integraci ladicího programu sady Visual Studio specifické pro AddressSanitizer.

Další informace o modulu runtime AddressSanitizer najdete v referenčních informacích k modulu runtime. Obsahuje informace o zachycených funkcích a o tom, jak připojit vlastní alokátory. Další informace o ukládání výpisů stavu systému ze selhání AddressSanitizer najdete v referenčních informacích k výpisu stavu systému.

Specifikace jazyka

__SANITIZE_ADDRESS__

Makro preprocesoru __SANITIZE_ADDRESS__ je definováno jako 1 při /fsanitize=address nastavení. Toto makro je užitečné pro pokročilé uživatele k podmíněnému zadání zdrojového kódu pro přítomnost modulu runtime AddressSanitizer.

#include <cstdio>

int main() {
    #ifdef __SANITIZE_ADDRESS__
        printf("Address sanitizer enabled");
    #else
        printf("Address sanitizer not enabled");
    #endif
    return 1;
}

__declspec(no_sanitize_address)

Specifikátor __declspec(no_sanitize_address) lze použít k selektivnímu zakázání sanitizátoru u funkcí, místních proměnných nebo globálních proměnných. To __declspec má vliv na chování kompilátoru , nikoli chování modulu runtime .

__declspec(no_sanitize_address)
void test1() {
    int x[100];
    x[100] = 5; // ASan exception not caught
}

void test2() {
    __declspec(no_sanitize_address) int x[100];
    x[100] = 5; // ASan exception not caught
}

__declspec(no_sanitize_address) int g[100];
void test3() {
    g[100] = 5; // ASan exception not caught
}

Compiler

/fsanitize=address Možnost kompilátoru

Možnost kompilátoru /fsanitize=address instrumentuje odkazy na paměť v kódu, aby zachytil chyby bezpečnosti paměti za běhu. Instrumentační háky se načítají, ukládají, obory allocaa funkce CRT. Dokáže rozpoznat skryté chyby, jako jsou mimo hranice, použití po volném rozsahu, použití po rozsahu atd. Seznam neexhaustivních chyb zjištěných za běhu najdete v příkladech chyb AddressSanitizer.

/fsanitize=address je kompatibilní se všemi existujícími úrovněmi optimalizace jazyka C++ nebo C (například /Od, /O1, /O2a /O2 /GL). Kód vytvořený pomocí této možnosti funguje se statickými a dynamickými crty (například /MD, /MDd, /MTa /MTd). Tuto možnost kompilátoru lze použít k vytvoření .EXE nebo .DLL cílení na x86 nebo x64. Pro optimální formátování zásobníků volání se vyžadují informace o ladění. Tato možnost kompilátoru není podporována s optimalizací s asistencí profilu.

Příklady kódu, které demonstruje několik druhů detekce chyb, najdete v příkladech chyb AddressSanitizer.

/fsanitize=fuzzer Možnost kompilátoru (experimentální)

Možnost /fsanitize=fuzzer kompilátoru přidá LibFuzzer do výchozího seznamu knihoven. Nastaví také následující možnosti pokrytí sanitizátoru:

Doporučujeme používat s /fsanitize=address /fsanitize=fuzzer.

Tyto knihovny se při zadání přidají /fsanitize=fuzzerdo výchozího seznamu knihoven:

Možnost modulu runtime Knihovna LibFuzzer
/MT clang_rt.fuzzer_MT-{arch}
/MD clang_rt.fuzzer_MD-{arch}
/MTd clang_rt.fuzzer_MTd-{arch}
/MDd clang_rt.fuzzer_MDd-{arch}

K dispozici jsou také knihovny LibFuzzer, které funkci vynechají main . Je vaší zodpovědností definovat main a volat LLVMFuzzerInitialize a LLVMFuzzerTestOneInput kdy tyto knihovny používáte. Pokud chcete použít některou z těchto knihoven, zadejte /NODEFAULTLIB a explicitně propojte následující knihovnu, která odpovídá vašemu modulu runtime a architektuře:

Možnost modulu runtime Knihovna no_main knihovny LibFuzzer
/MT clang_rt.fuzzer_no_main_MT-{arch}
/MD clang_rt.fuzzer_no_main_MD-{arch}
/MTd clang_rt.fuzzer_no_main_MTd-{arch}
/MDd clang_rt.fuzzer_no_main_MDd-{arch}

Pokud zadáte některou z těchto knihoven a nezadáte /NODEFAULTLIB ji, zobrazí se nevyřešená chyba odkazu na externí symbol.

/fsanitize-address-use-after-return Možnost kompilátoru (experimentální)

Kompilátor MSVC (na rozdíl od jazyka Clang) ve výchozím nastavení negeneruje kód pro přidělení rámců v haldě za účelem zachycení chyb použití po vrácení. Chcete-li zachytit tyto chyby pomocí AddressSanitizer, musíte:

  1. Zkompilujte pomocí /fsanitize-address-use-after-return možnosti.
  2. Před spuštěním programu spusťte set ASAN_OPTIONS=detect_stack_use_after_return=1 nastavení možnosti kontroly za běhu.

Tato /fsanitize-address-use-after-return možnost způsobí, že kompilátor vygeneruje kód tak, aby v haldě používal duální rámec zásobníku, když se místní hodnoty považují za "pořízenou adresu". Tento kód je mnohem pomalejší než jen použití /fsanitize=address samotného kódu. Další informace a příklad naleznete v tématu Chyba: stack-use-after-return.

Duální rámec zásobníku v haldě zůstane po návratu z funkce, která ji vytvořila. Představte si příklad, kdy se po návratu použije adresa místního, přiděleného slotu v haldě. Stínové bajty přidružené k rámečku falešné haldy obsahují hodnotu 0xF9. Tato 0xF9 znamená chybu typu stack-use-after-return, když modul runtime hlásí chybu.

Rámce zásobníku se přidělují v haldě a zůstanou po vrácení funkcí. Modul runtime používá uvolňování paměti k asynchronnímu uvolnění těchto falešných objektů v rámci volání po určitém časovém intervalu. Adresy místních počítačů se přenesou na trvalé snímky v haldě. Systém dokáže zjistit, kdy se po definování funkce použijí všechny místní hodnoty. Další informace najdete v algoritmu použití zásobníku po vrácení , jak je dokumentováno společností Google.

Linker

/INFERASANLIBS[:NO] možnost linkeru

Možnost /fsanitize=address kompilátoru označí objekty k určení, kterou knihovnu AddressSanitizer chcete propojit se spustitelným souborem. Knihovny mají názvy, které začínají clang_rt.asan*. Možnost linkeru /INFERASANLIBS (ve výchozím nastavení) tyto knihovny automaticky propojí z jejich výchozích umístění. Tady jsou vybrané a automaticky propojené knihovny.

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. KonvenceMSch x86 x64 i386 x86_64 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}

Možnost linkeru /INFERASANLIBS:NO zabrání propojení clang_rt.asan* souboru knihovny z výchozího umístění. Pokud použijete tuto možnost, přidejte cestu knihovny do skriptů sestavení. V opačném případě linker hlásí nevyřešenou chybu externího symbolu.

Předchozí verze

Před verzí Visual Studio 17.7 Preview 3 nepoužíly staticky propojené (/MT nebo /MTd) sestavení 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 /MTd) také 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.

Možnost modulu runtime CRT KNIHOVNA DLL nebo EXE Knihovny modulu runtime AddressSanitizer
/MT EXE clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch}
/MT DLL clang_rt.asan_dll_thunk-{arch}
/MD Kteroukoli clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch}
/MTd EXE clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch}
/MTd DLL clang_rt.asan_dbg_dll_thunk-{arch}
/MDd Kteroukoli clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch}

Integrace se sadou Visual Studio

/fno-sanitize-address-vcasan-lib Možnost kompilátoru

Odkazy /fsanitize=address na možnosti v dalších knihovnách pro vylepšené ladění sady Visual Studio při vyvolání výjimky AddressSanitizer. Tyto knihovny se nazývají VCAsan. Knihovny umožňují sadě Visual Studio zobrazit chyby AddressSanitizer ve zdrojovém kódu. Umožňují spustitelnému souboru také generovat výpisy stavu systému při vytvoření zprávy o chybě AddressSanitizer. Další informace naleznete v tématu Visual Studio AddressSanitizer extended functionality library.

Vybraná knihovna závisí na možnostech kompilátoru a je automaticky propojena.

Možnost modulu runtime Verze VCAsan
/MT libvcasan.lib
/MD vcasan.lib
/MTd libvcasand.lib
/MDd vcasand.lib

Pokud ale zkompilujete ( /Zl vynecháte výchozí název knihovny), musíte knihovnu zadat ručně. Pokud to neuděláte, zobrazí se chyba propojení s nevyřešeným externím symbolem. Zde je uvedeno několik typických příkladů:

error LNK2001: unresolved external symbol __you_must_link_with_VCAsan_lib
error LNK2001: unresolved external symbol ___you_must_link_with_VCAsan_lib

Vylepšené ladění lze v době kompilace zakázat pomocí této /fno-sanitize-address-vcasan-lib možnosti.

ASAN_VCASAN_DEBUGGING proměnná prostředí

Možnost /fsanitize=address kompilátoru vytvoří binární soubor, který za běhu zveřejňuje chyby zabezpečení paměti. Při spuštění binárního souboru z příkazového řádku a modul runtime hlásí chybu, vytiskne podrobnosti o chybě. Potom proces ukončí. ASAN_VCASAN_DEBUGGING Proměnnou prostředí lze nastavit tak, aby se integrované vývojové prostředí sady Visual Studio spustilo okamžitě, když modul runtime hlásí chybu. Tato možnost kompilátoru umožňuje zobrazit chybu nad zdrojovým kódem na přesném řádku a sloupci, který chybu způsobil.

Pokud chcete toto chování povolit, spusťte příkaz set ASAN_VCASAN_DEBUGGING=1 před spuštěním aplikace. Rozšířené ladění můžete zakázat spuštěním set ASAN_VCASAN_DEBUGGING=0příkazu .

Viz také

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