AddressSanitizer
Overzicht
De C & C++-talen zijn krachtig, maar kunnen last hebben van een klasse bugs die van invloed zijn op de juistheid van het programma en de beveiliging van het programma. Vanaf Visual Studio 2019 versie 16.9 ondersteunt de Microsoft C/C++-compiler (MSVC) en IDE de AddressSanitizer opschoning. AddressSanitizer (ASan) is een compiler- en runtimetechnologie die veel moeilijk te vinden bugs blootstelt met nul fout-positieven:
-
niet-overeenkomende toewijzingen/dealloc's en
new
/delete
type komen niet overeen - toewijzingen te groot voor de heap-
-
calloc
overloop enalloca
overloop - Double free and use after free
- globale variabele overloop
- Heap-buffer overloop
- Ongeldige uitlijning van uitgelijnde waarden
-
memcpy
- enstrncat
parameter overlappen - Stack-bufferoverloop en onderloop
-
Stack gebruiken na
return
en gebruiken na bereik - geheugengebruik nadat het is vergiftigd
Gebruik AddressSanitizer om uw tijd te verminderen die u hebt besteed aan:
- Basis correctheid
- Platformoverschrijdende draagbaarheid
- Veiligheid
- Stresstests
- Nieuwe code integreren
AddressSanitizer, oorspronkelijk geïntroduceerd door Google, biedt runtime bug-finding technologieën die uw bestaande buildsystemen en bestaande testassets rechtstreeks gebruiken.
AddressSanitizer is geïntegreerd met het Visual Studio-projectsysteem, het CMake-buildsysteem en de IDE. Projecten kunnen AddressSanitizer inschakelen door een projecteigenschap in te stellen of door een extra compileroptie te gebruiken: /fsanitize=address
. De nieuwe optie is compatibel met alle niveaus van optimalisatie en configuraties van x86 en x64. Het is echter niet compatibel met bewerken en doorgaan, incrementele koppelingen /RTC
.
Vanaf Visual Studio 2019 versie 16.9 maakt de AddressSanitizer-technologie van Microsoft integratie mogelijk met de Visual Studio IDE. De functionaliteit kan eventueel een crashdumpbestand maken wanneer de opschoningsfunctie tijdens runtime een fout vindt. Als u de omgevingsvariabele ASAN_SAVE_DUMPS=MyFileName.dmp
instelt voordat u uw programma uitvoert, wordt er een crashdumpbestand gemaakt met extra metagegevens voor efficiënte post-mortem-foutopsporing van nauwkeurig opgegeven fouten. Deze dumpbestanden maken uitgebreid gebruik van AddressSanitizer eenvoudiger voor:
- Testen van lokale machines
- On-premises gedistribueerde tests
- Cloudwerkstromen voor testen
AddressSanitizer installeren
C++-workloads in het Installatieprogramma van Visual Studio installeren standaard de AddressSanitizer-bibliotheken en IDE-integratie. Als u echter een upgrade uitvoert van een oudere versie van Visual Studio 2019, gebruikt u het installatieprogramma om ASan-ondersteuning in te schakelen na de upgrade. U kunt het installatieprogramma openen vanuit het hoofdmenu van Visual Studio via Tools>Extra en onderdelen ophalen... Kies wijzigen op uw bestaande Visual Studio-installatie vanuit het Visual Studio-installatieprogramma om naar het volgende scherm te gaan.
Notitie
Als u Visual Studio uitvoert op de nieuwe update, maar ASan nog niet hebt geïnstalleerd, krijgt u een foutmelding wanneer u uw code uitvoert:
LNK1356: bibliotheek 'clang_rt.asan_dynamic-i386.lib' niet vinden
AddressSanitizer gebruiken
Begin met het bouwen van uw uitvoerbare bestanden met de /fsanitize=address
compileroptie met behulp van een van deze algemene ontwikkelmethoden:
- Builds van opdrachtregels
- Visual Studio-projectsysteem
- Visual Studio CMake-integratie
Hercompileer en voer vervolgens uw programma normaal uit. Deze codegeneratie maakt vele soorten nauwkeurig agnose foutenbeschikbaar. Deze fouten worden op drie manieren gerapporteerd: in de foutopsporingsprogramma-IDE, op de opdrachtregel of opgeslagen in een nieuw type dumpbestand voor nauwkeurige off-line verwerking.
Microsoft raadt u aan AddressSanitizer te gebruiken in deze drie standaardwerkstromen:
interne lus voor ontwikkelaars
- Visual Studio - opdrachtregel
- Visual Studio - Project-systeem
- Visual Studio - CMake-
CI/CD- - continue integratie/continue ontwikkeling
- Foutrapportage : nieuwe AddressSanitizer-dumpbestanden
Fuzzing - gebouw met de libFuzzer wrapper
- Azure OneFuzz-
- Lokale machine
In dit artikel wordt beschreven welke informatie u nodig hebt om de drie eerder vermelde werkstromen in te schakelen. De informatie is specifiek voor de platformafhankelijke Windows 10 (en hoger) implementatie van AddressSanitizer. Deze documentatie is een aanvulling op de uitstekende documentatie van Google, Apple en GCC al gepubliceerd.
Notitie
Ondersteuning is beperkt tot x86 en x64 in Windows 10 en hoger.
Stuur ons feedback over wat u in toekomstige releases wilt zien. Uw feedback helpt ons prioriteit te geven aan andere opschoningen voor de toekomst, zoals /fsanitize=thread
, /fsanitize=leak
, /fsanitize=memory
, /fsanitize=undefined
of /fsanitize=hwaddress
. U kunt hier fouten melden als u problemen ondervindt.
AddressSanitizer gebruiken vanuit een opdrachtprompt voor ontwikkelaars
Gebruik de optie /fsanitize=address
compiler in een opdrachtprompt voor ontwikkelaars om compiling in te schakelen voor de AddressSanitizer-runtime. De optie /fsanitize=address
is compatibel met bestaande C++ of C-optimalisatieniveaus (bijvoorbeeld /Od
, /O1
, /O2
en /O2 /GL
). De optie werkt met statische en dynamische CRT's (bijvoorbeeld /MD
, /MDd
, /MT
en /MTd
). Het werkt of u een EXE of een DLL maakt. Foutopsporingsinformatie is vereist voor een optimale opmaak van aanroepstacks. In het volgende voorbeeld wordt cl /fsanitize=address /Zi
doorgegeven op de opdrachtregel.
Notitie
AddressSanitizer biedt geen ondersteuning voor PGO (Profile-Guided Optimization). AddressSanitizer mag niet worden gebruikt in productie.
De AddressSanitizer-bibliotheken (.lib-bestanden) worden automatisch aan u gekoppeld. Zie AddressSanitizer-taal, build- en foutopsporingsreferentievoor meer informatie.
Voorbeeld: algemene bufferoverloop basis
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Compileer main.cpp
met behulp van een opdrachtprompt voor ontwikkelaars voor Visual Studio 2019 met behulp van /fsanitize=address /Zi
Wanneer u de resulterende main.exe
uitvoert op de opdrachtregel, wordt het opgemaakte foutenrapport gemaakt dat volgt.
Houd rekening met de overlappende, rode vakken die zeven belangrijke gegevens markeren:
Er zijn zeven rode markeringen die belangrijke gegevens in het foutenrapport identificeren. Ze worden toegewezen aan de genummerde lijst die volgt op deze schermopname. In de genummerde vakken wordt de volgende tekst gemarkeerd: 1) global-buffer-overflow 2) WRITE of size 4 3) basic-global-overflow.cpp 7 4) rechts van globale variabele 'x' gedefinieerd in 'basic-global-overflow.cpp:3:8' 5) van grootte 400 6) 00 00[f9]f9 f9 7) Box bevindt zich in het legendagebied schaduw byte en bevat globale rode zone: f9
Rode markeringen, van boven naar beneden
- De geheugenveiligheidsfout is een wereldwijde buffer-overloop.
- Er zijn 4 bytes (32 bits) opgeslagen buiten een door de gebruiker gedefinieerde variabele.
- Het archief vond plaats in functie
main()
gedefinieerd in bestandbasic-global-overflow.cpp
op regel 7. - De variabele met de naam
x
wordt gedefinieerd in basic-global-overflow.cpp op regel 3, beginnend bij kolom 8 - Deze globale variabele
x
heeft een grootte van 400 bytes - De exacte schaduw-byte die het adres beschrijft waarop het archief is gericht, had een waarde van
0xf9
- De legenda voor schaduwbytes zegt dat
0xf9
een gebied is van opvulling rechts vanint x[100]
Notitie
De functienamen in de aanroepstack worden geproduceerd via de LLVM symboliserende die na een fout door de runtime wordt aangeroepen.
AddressSanitizer gebruiken in Visual Studio
AddressSanitizer is geïntegreerd met de Visual Studio IDE. Als u AddressSanitizer wilt inschakelen voor een MSBuild-project, klikt u met de rechtermuisknop op het project in Solution Explorer en kiest u Eigenschappen. Selecteer in het dialoogvenster eigenschappenpagina'sconfiguratie-eigenschappen>C/C++>Algemeenen wijzig vervolgens de eigenschap AddressSanitizer inschakelen. Kies OK- om uw wijzigingen op te slaan.
Als u wilt bouwen vanuit de IDE, moet u zich afmelden voor incompatibele opties. Voor een bestaand project dat is gecompileerd met behulp van /Od
(of de foutopsporingsmodus), moet u mogelijk deze opties uitschakelen:
- bewerken uitschakelen en doorgaan met
-
/RTC1
(runtimecontroles) uitschakelen -
/INCREMENTAL
(incrementeel koppelen) uitschakelen
Druk op F5om het foutopsporingsprogramma te bouwen en uit te voeren. Er wordt een uitzondering gegenereerd venster weergegeven in Visual Studio:
AddressSanitizer gebruiken vanuit Visual Studio: CMake
Voer de volgende stappen uit om AddressSanitizer in te schakelen voor een CMake-project dat is gemaakt voor het doel van Windows:
Open de vervolgkeuzelijst Configurations in de werkbalk boven aan de IDE en selecteer Configuraties beheren.
Hiermee opent u de CMake Project Settings-editor, die de inhoud van het
CMakeSettings.json
-bestand van uw project weergeeft.Kies de koppeling JSON- bewerken in de editor. Met deze selectie wordt de weergave overgeschakeld naar onbewerkte JSON.
Voeg het volgende codefragment toe aan de vooraf ingestelde
"windows-base"
, in"configurePresets":
om adresontschoning in te schakelen:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }
"configurePresets"
ziet er daarna ongeveer als volgt uit:"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" } },
Adres opschoning werkt niet als bewerken en doorgaan is opgegeven (
/ZI
), die standaard is ingeschakeld voor nieuwe CMake-projecten. Maak inCMakeLists.txt
commentaar (voorvoegsel met#
) de regel die begint metset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"
. Die lijn ziet er daarna ongeveer als volgt uit:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
Voer Ctrl+S- in om dit JSON-bestand op te slaan
Wis de map van de CMake-cache en configureer opnieuw door een keuze te maken in het Menu van Visual Studio: Project>Cache verwijderen enopnieuw configureren. Kies Ja wanneer de prompt wordt weergegeven om uw cachemap te wissen en opnieuw te configureren.
Vervang de inhoud van het bronbestand (bijvoorbeeld
CMakeProject1.cpp
) door het volgende:// 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; }
Kies F5- om opnieuw te compileren en uit te voeren onder het foutopsporingsprogramma.
In deze schermopname wordt de fout van de CMake-build vastgelegd.
AddressSanitizer-crashdumps
We hebben nieuwe functionaliteit geïntroduceerd in AddressSanitizer voor gebruik met cloud- en gedistribueerde werkstromen. Met deze functionaliteit kan een AddressSanitizer-fout offline worden weergegeven in de IDE. De fout wordt over de bron heen geplakt, net zoals in een live foutopsporingssessie.
Deze nieuwe dumpbestanden kunnen leiden tot efficiëntie bij het analyseren van een bug. U hoeft niet opnieuw te worden uitgevoerd of externe gegevens te zoeken of te zoeken naar een computer die offline is gegaan.
Een nieuw type dumpbestand maken dat op een later tijdstip kan worden weergegeven in Visual Studio op een andere computer:
set ASAN_SAVE_DUMPS=MyFileName.dmp
Vanaf Visual Studio 16.9 kunt u een nauwkeurig opgegeven fout weergeven, opgeslagen in uw *.dmp
bestand, boven op uw broncode.
Deze nieuwe crashdumpfunctionaliteit cloudwerkstromen of gedistribueerde tests mogelijk maakt. Het kan ook worden gebruikt voor het indienen van een gedetailleerde, bruikbare fout in elk scenario.
Voorbeeldfouten
AddressSanitizer kan verschillende soorten fouten met geheugenfouten detecteren. Hier volgen veel runtimefouten die worden gerapporteerd wanneer u de binaire bestanden uitvoert die zijn gecompileerd met behulp van de optie AddressSanitizer (/fsanitize=address
) compiler:
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
Zie AddressSanitizer-foutvoorbeeldenvoor meer informatie over de voorbeelden.
Verschillen met Clang 12.0
MSVC verschilt momenteel van Clang 12.0 in twee functionele gebieden:
- stack-use-after-scope: deze instelling is standaard ingeschakeld en kan niet worden uitgeschakeld.
-
stack-use-after-return-: deze functionaliteit vereist een extra compileroptie en is niet beschikbaar door alleen
ASAN_OPTIONS
in te stellen.
Deze beslissingen zijn genomen om de testmatrix te verminderen die nodig is om deze eerste versie te leveren.
Functies die kunnen leiden tot fout-positieven in Visual Studio 2019 16.9, zijn niet opgenomen. Deze discipline dwingt de effectieve testintegriteit af die nodig is bij het overwegen van interop met tientallen jaren bestaande code. In latere releases kunnen meer mogelijkheden worden overwogen:
- Initialisatievolgorde Fiasco
- intra objectoverloop
- Container Overflow-
- aanwijzer aftrekken/vergelijken
Zie Building for AddressSanitizer met MSVCvoor meer informatie.
Bestaande documentatie voor de branche
Er bestaat al uitgebreide documentatie voor deze taal- en platformafhankelijke implementaties van de AddressSanitizer-technologie.
In dit seminale document over de AddressSanitizer (extern) wordt de implementatie beschreven.
Zie ook
AddressSanitizer bekende problemen
AddressSanitizer-build- en taalreferenties
naslaginformatie over AddressSanitizer-runtime
addressSanitizer schaduwbytes
AddressSanitizer-cloud of gedistribueerde tests
integratie van AddressSanitizer-foutopsporingsprogramma's
voorbeelden van AddressSanitizer-fouten