AddressSanitizer
Přehled
Jazyky C & C++ jsou výkonné, ale mohou trpět třídou chyb, které ovlivňují správnost programu a zabezpečení programu. Počínaje sadou Visual Studio 2019 verze 16.9 podporuje kompilátor Microsoft C/C++ (MSVC) a integrované vývojové prostředí ( IDE) sanitizer AddressSanitizer . AddressSanitizer (ASan) je technologie kompilátoru a modulu runtime, která zveřejňuje mnoho těžko najít chyb s nulovými falešně pozitivními výsledky:
- Neshody přidělení nebo zrušení přidělení a/
new
delete
neshody typů - Přidělení pro haldu je příliš velká.
calloc
přetečení aalloca
přetečení- Double free and use after free
- Globální přetečení proměnných
- Přetečení vyrovnávací paměti haldy
- Neplatné zarovnání zarovnaných hodnot
memcpy
astrncat
překrývání parametrů- Přetečení vyrovnávací paměti zásobníku a podtečení
- Použití zásobníku po
return
a použití po rozsahu - Využití paměti po otrávené
Použijte AddressSanitizer ke zkrácení času stráveného na:
- Základní správnost
- Přenositelnost napříč platformami
- Zabezpečení
- Zátěžové testování
- Integrace nového kódu
AddressSanitizer, původně představený Společností Google, poskytuje technologie pro vyhledávání chyb za běhu, které používají stávající systémy sestavení a existující testovací prostředky přímo.
AddressSanitizer je integrovaný se systémem projektů sady Visual Studio, se systémem sestavení CMake a integrovaným vývojovým prostředím. Projekty mohou povolit AddressSanitizer nastavením vlastnosti projektu nebo pomocí jedné další možnosti kompilátoru: /fsanitize=address
. Nová možnost je kompatibilní se všemi úrovněmi optimalizace a konfigurací x86 a x64. Není však kompatibilní s úpravami a pokračováním, přírůstkovým propojením a /RTC
.
Od sady Visual Studio 2019 verze 16.9 technologie AddressSanitizer společnosti Microsoft umožňuje integraci s integrovaným vývojovém prostředím sady Visual Studio. Funkce může volitelně vytvořit soubor s výpisem stavu systému, když sanitizátor najde chybu za běhu. Pokud před spuštěním programu nastavíte ASAN_SAVE_DUMPS=MyFileName.dmp
proměnnou prostředí, vytvoří se soubor s výpisem stavu systému s dalšími metadaty pro efektivní následné ladění přesně diagnostikovaných chyb. Tyto soubory s výpisem paměti usnadňují rozšířené použití AddressSanitizeru pro:
- Místní strojové testování
- Místní distribuované testování
- Cloudové pracovní postupy pro testování
Instalace AddressSanitizer
Úlohy C++ v Instalační program pro Visual Studio ve výchozím nastavení nainstalují knihovny AddressSanitizer a integraci integrovaného vývojového prostředí (IDE). Pokud ale upgradujete ze starší verze sady Visual Studio 2019, povolte po upgradu podporu ASan pomocí instalačního programu. Instalační program můžete otevřít z hlavní nabídky sady Visual Studio prostřednictvím nástrojů>Získat nástroje a funkce... V Instalační program pro Visual Studio zvolte Upravit ve stávající instalaci sady Visual Studio, abyste se dostali na následující obrazovku.
Poznámka:
Pokud visual Studio spustíte v nové aktualizaci, ale nenainstalovali jste ASan, při spuštění kódu se zobrazí chyba:
LNK1356: Nelze najít knihovnu clang_rt.asan_dynamic-i386.lib.
Použití AddressSanitizeru
Začněte vytvářet spustitelné soubory s možností kompilátoru /fsanitize=address
pomocí některé z těchto běžných metod vývoje:
- Sestavení příkazového řádku
- Projektový systém sady Visual Studio
- Integrace CMake sady Visual Studio
Znovu zkompilujte a pak program normálně spusťte. Tato generace kódu zveřejňuje mnoho typů přesně diagnostikovaných chyb. Tyto chyby se oznamují třemi způsoby: v integrovaném vývojovém prostředí ladicího programu, na příkazovém řádku nebo uloženém v novém typu souboru s výpisem paměti pro přesné off-line zpracování.
Microsoft doporučuje používat AddressSanitizer v těchto třech standardních pracovních postupech:
Vnitřní smyčka pro vývojáře
- Visual Studio – příkazový řádek
- Visual Studio – Projektový systém
- Visual Studio – CMake
CI/CD – kontinuální integrace / průběžný vývoj
- Zasílání zpráv o chybách – Soubory výpisu stavu systému New AddressSanitizer
Fuzzing - budova s obálkou libFuzzer
- Azure OneFuzz
- Místní počítač
Tento článek popisuje informace, které potřebujete k povolení výše uvedených tří pracovních postupů. Informace jsou specifické pro implementaci AddressSanitizer závislé na platformě Windows 10 (a novější). Tato dokumentace doplňuje vynikající dokumentaci od Společnosti Google, Apple a GCC již publikované.
Poznámka:
Podpora je omezená na x86 a x64 ve Windows 10 a novějších verzích. Pošlete nám svůj názor na to, co byste chtěli vidět v budoucích verzích. Vaše zpětná vazba nám pomáhá určit prioritu jiných sanitizátorů pro budoucnost, například /fsanitize=thread
, /fsanitize=leak
, /fsanitize=memory
, /fsanitize=undefined
nebo /fsanitize=hwaddress
. Pokud narazíte na problémy, můžete zde nahlásit chyby.
Použití AddressSanitizer z příkazového řádku vývojáře
Pomocí možnosti kompilátoru /fsanitize=address
na příkazovém řádku vývojáře povolte kompilaci pro modul runtime AddressSanitizer. Možnost /fsanitize=address
je kompatibilní se všemi existujícími úrovněmi optimalizace C++ nebo C (například /Od
, /O1
, /O2
, /O2 /GL
a PGO
). Tato možnost funguje se statickými a dynamickými crty (například /MD
, /MDd
, /MT
, a /MTd
). Funguje bez ohledu na to, zda vytváříte EXE nebo DLL. Pro optimální formátování zásobníků volání se vyžadují informace o ladění. V následujícím příkladu cl /fsanitize=address /Zi
se předá na příkazovém řádku.
Knihovny AddressSanitizer (soubory .lib) jsou pro vás automaticky propojeny. Další informace naleznete v tématu Jazyk AddressSanitizer, sestavení a ladění reference.
Příklad – základní přetečení globální vyrovnávací paměti
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Použití příkazového řádku vývojáře pro Visual Studio 2019, kompilace main.cpp
pomocí /fsanitize=address /Zi
Když spustíte výsledek main.exe
na příkazovém řádku, vytvoří se následující formátovaná zpráva o chybách.
Zvažte překryvná červená pole, která zvýrazňují sedm klíčových informací:
V sestavě chyb je sedm červených zvýraznění identifikující klíčové informace. Namapují se na číslovaný seznam, který následuje za tímto snímkem obrazovky. Číslovaná pole zvýrazňují následující text: 1) globální přetečení vyrovnávací paměti 2) ZÁPIS o velikosti 4 3) basic-global-overflow.cpp 7 4) napravo od globální proměnné x definované v oblasti "basic-global-overflow.cpp:3:8" 5) velikosti 400 6) 00 00[f9]f9 f9 7) Pole je ve stínové bajtové oblasti legendy a obsahuje globální červené pásmo: f9
Červené zvýraznění shora dolů
- Chyba bezpečnosti paměti je globální přetečení vyrovnávací paměti.
- Byly uloženy 4 bajty (32 bitů) mimo libovolnou uživatelsky definovanou proměnnou.
- Úložiště proběhlo ve funkci
main()
definované v souborubasic-global-overflow.cpp
na řádku 7. - Pojmenovaná proměnná
x
se definuje v basic-global-overflow.cpp na řádku 3 počínaje sloupcem 8. - Tato globální proměnná
x
má velikost 400 bajtů. - Přesný stínový bajt popisující adresu cílenou úložištěm měla hodnotu
0xf9
- Legenda stínového bajtu říká
0xf9
, že je oblast odsazení napravo odsazení.int x[100]
Poznámka:
Názvy funkcí v zásobníku volání se vytvářejí prostřednictvím symbolizátoru LLVM, který je vyvolán modulem runtime při chybě.
Použití AddressSanitizeru v sadě Visual Studio
AddressSanitizer je integrovaný do integrovaného vývojového prostředí sady Visual Studio. Chcete-li zapnout AddressSanitizer pro projekt MSBuild, klikněte pravým tlačítkem myši na projekt v Průzkumník řešení a zvolte Vlastnosti. V dialogovém okně Stránky vlastností vyberte Vlastnosti>konfigurace C/C++>Obecné a pak upravte vlastnost Enable AddressSanitizer. Kliknutím na OK uložte provedené změny.
Pokud chcete vytvářet z integrovaného vývojového prostředí, odhlaste se z nekompatibilních možností. U existujícího projektu kompilovaného pomocí /Od
(nebo režimu ladění) možná budete muset vypnout tyto možnosti:
- Vypnutí úprav a pokračování
- Vypnutí
/RTC1
(kontroly za běhu) - Vypnutí
/INCREMENTAL
(přírůstkové propojení)
Ladicí program sestavíte a spustíte stisknutím klávesy F5. V sadě Visual Studio se zobrazí okno vyvolání výjimky:
Použití AddressSanitizer ze sady Visual Studio: CMake
Chcete-li povolit AddressSanitizer pro projekt CMake vytvořený pro cílový systém Windows, postupujte takto:
Otevřete rozevírací seznam Konfigurace na panelu nástrojů v horní části integrovaného vývojového prostředí a vyberte Spravovat konfigurace.
Tím se otevře editor nastavení projektu CMake, který odráží obsah souboru projektu
CMakeSettings.json
.V editoru zvolte odkaz Upravit JSON . Tento výběr přepne zobrazení na nezpracovaný formát JSON.
Do přednastaveného
"windows-base"
nastavení přidejte následující fragment kódu, aby"configurePresets":
se zapnula adresa Sanitizer:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }
"configurePresets"
vypadá přibližně takto:"configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" }, "environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" } },
Sanitizátor adresy nefunguje, pokud je zadán parametr edit-and-continue (
/ZI
), který je ve výchozím nastavení povolený pro nové projekty CMake. VCMakeLists.txt
, okomentovat (předpona#
) řádek, který začínáset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"
na . Tento řádek vypadá přibližně takto:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
Pokud chcete uložit tento soubor JSON, zadejte Ctrl+S .
Vymažte adresář mezipaměti CMake a překonfigurujte tak, že zvolíte z nabídky sady Visual Studio: Mezipaměť Pro odstranění projektu>a změna konfigurace. Po zobrazení výzvy zvolte Ano , aby se adresář mezipaměti vymaže a znovu nakonfiguruje.
Obsah zdrojového souboru (například
CMakeProject1.cpp
) nahraďte následujícím kódem:// CMakeProject1.cpp : Defines the entry point for the application #include <stdio.h> int x[100]; int main() { printf("Hello!\n"); x[100] = 5; // Boom! return 0; }
Zvolte F5 , chcete-li překompilovat a spustit pod ladicím programem.
Tento snímek obrazovky zachycuje chybu z sestavení CMake.
Výpisy stavu systému AddressSanitizer
V AddressSanitizer jsme zavedli nové funkce pro použití s cloudovými a distribuovanými pracovními postupy. Tato funkce umožňuje offline zobrazení chyby AddressSanitizer v integrovaném vývojovém prostředí (IDE). Chyba se nad zdrojem překryje, stejně jako byste měli zkušenosti v živé ladicí relaci.
Tyto nové soubory s výpisem paměti můžou při analýze chyby vést k efektivitě. Nemusíte znovu sjíždět ani hledat vzdálená data nebo hledat počítač, který se odešel mimo linku.
Pokud chcete vytvořit nový typ souboru s výpisem paměti, který je možné zobrazit v sadě Visual Studio na jiném počítači později:
set ASAN_SAVE_DUMPS=MyFileName.dmp
Počínaje sadou Visual Studio 16.9 můžete zobrazit přesně diagnostickou chybu uloženou v *.dmp
souboru nad zdrojovým kódem.
Tato nová funkce výpisu stavu systému umožňuje cloudové pracovní postupy nebo distribuované testování. Dá se také použít k vytvoření podrobné chyby s možností použití v jakémkoli scénáři.
Příklady chyb
AddressSanitizer dokáže rozpoznat několik druhů chyb zneužití paměti. Tady je mnoho chyb modulu runtime hlášených při spuštění binárních souborů zkompilovaných pomocí možnosti kompilátoru AddressSanitizer (/fsanitize=address
):
alloc-dealloc-mismatch
allocation-size-too-big
calloc-overflow
double-free
dynamic-stack-buffer-overflow
global-buffer-overflow
heap-buffer-overflow
heap-use-after-free
invalid-allocation-alignment
memcpy-param-overlap
new-delete-type-mismatch
stack-buffer-overflow
stack-buffer-underflow
stack-use-after-return
stack-use-after-scope
strncat-param-overlap
use-after-poison
Další informace o příkladech najdete v tématu Příklady chyb AddressSanitizer.
Rozdíly v jazyce Clang 12.0
MSVC se v současné době liší od jazyka Clang 12.0 ve dvou funkčních oblastech:
- stack-use-after-scope – toto nastavení je ve výchozím nastavení zapnuté a nejde ho vypnout.
- stack-use-after-return – tato funkce vyžaduje další možnost kompilátoru a není dostupná pouze nastavením
ASAN_OPTIONS
.
Tato rozhodnutí byla provedena, aby se snížila testovací matice potřebná k doručení této první verze.
Funkce, které by mohly vést k falešně pozitivním výsledkům v sadě Visual Studio 2019 16.9, nebyly zahrnuty. Tato disciplína vynucuje efektivní integritu testování potřebnou při zvažování spolupráce s desetiletími stávajícího kódu. V pozdějších verzích je možné zvážit další možnosti:
- Pořadí inicializace Fiasco
- Vnitřní přetečení objektu
- Přetečení kontejneru
- Odčítání/porovnání ukazatele
Další informace naleznete v tématu Building for AddressSanitizer s MSVC.
Stávající oborová dokumentace
Rozsáhlá dokumentace již existuje pro tyto implementace závislé na jazyce a platformě technologie AddressSanitizer.
Tento středník na AddressSanitizer (externí) popisuje implementaci.
Viz také
Známé problémy s addressSanitizerem
Referenční dokumentace k sestavení a jazyku AddressSanitizer
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