AddressSanitizer
Omówienie
Języki C & C++ są zaawansowane, ale mogą cierpieć na klasy usterek, które wpływają na poprawność programu i zabezpieczenia programu. Począwszy od programu Visual Studio 2019 w wersji 16.9, kompilator Microsoft C/C++ (MSVC) i środowisko IDE obsługuje sanitizer AddressSanitizer . AddressSanitizer (ASan) to technologia kompilatora i środowiska uruchomieniowego, która uwidacznia wiele trudnych do znalezienia błędów z zerowymi wynikami fałszywie dodatnimi:
- Niezgodność alloc/dealloc i/
new
delete
niezgodność typów - Alokacje za duże dla sterty
calloc
przepełnienie ialloca
przepełnienie- Bezpłatna i bezpłatna
- Przepełnienie zmiennej globalnej
- Przepełnienie buforu stert
- Nieprawidłowe wyrównanie wyrównanych wartości
memcpy
nakładanie się parametrów istrncat
- Przepełnienie i niedopełnienie buforu stosu
- Użycie stosu po
return
i użyciu po zakresie - Użycie pamięci po jego zatrucie
Użyj narzędzia AddressSanitizer, aby skrócić czas spędzony na:
- Poprawność podstawowa
- Przenośność międzyplatformowa
- Zabezpieczenia
- Testy obciążeniowe
- Integrowanie nowego kodu
AddressSanitizer, pierwotnie wprowadzony przez firmę Google, udostępnia technologie znajdowania błędów środowiska uruchomieniowego, które używają istniejących systemów kompilacji i istniejących zasobów testowych bezpośrednio.
AddressSanitizer jest zintegrowany z systemem projektu Visual Studio, systemem kompilacji CMake i środowiskiem IDE. Projekty mogą włączyć element AddressSanitizer, ustawiając właściwość projektu lub używając jednej dodatkowej opcji kompilatora: /fsanitize=address
. Nowa opcja jest zgodna ze wszystkimi poziomami optymalizacji i konfiguracji x86 i x64. Nie jest jednak zgodny z funkcją edytowania i kontynuowania, łączenia przyrostowego i /RTC
.
Począwszy od programu Visual Studio 2019 w wersji 16.9 technologia AddressSanitizer firmy Microsoft umożliwia integrację ze środowiskiem IDE programu Visual Studio. Funkcje mogą opcjonalnie utworzyć plik zrzutu awaryjnego, gdy sanitizer znajdzie usterkę w czasie wykonywania. Jeśli ustawisz zmienną ASAN_SAVE_DUMPS=MyFileName.dmp
środowiskową przed uruchomieniem programu, zostanie utworzony plik zrzutu awaryjnego z dodatkowymi metadanymi na potrzeby wydajnego debugowania pośmiertnego precyzyjnego diagnozowania usterek. Te pliki zrzutu ułatwiają rozszerzone korzystanie z narzędzia AddressSanitizer:
- Testowanie maszyn lokalnych
- Lokalne testowanie rozproszone
- Przepływy pracy oparte na chmurze na potrzeby testowania
Instalowanie narzędzia AddressSanitizer
Obciążenia języka C++ w Instalator programu Visual Studio domyślnie instalują biblioteki AddressSanitizer i integrację środowiska IDE. Jeśli jednak uaktualniasz starszą wersję programu Visual Studio 2019, użyj Instalatora, aby włączyć obsługę aplikacji ASan po uaktualnieniu. Instalator można otworzyć z menu głównego programu Visual Studio za pomocą narzędzi Pobierz narzędzia>i funkcje... Wybierz pozycję Modyfikuj w istniejącej instalacji programu Visual Studio z Instalator programu Visual Studio, aby przejść do następującego ekranu.
Uwaga
Jeśli uruchomisz program Visual Studio w nowej aktualizacji, ale nie zainstalowano narzędzia ASan, podczas uruchamiania kodu wystąpi błąd:
LNK1356: nie można odnaleźć biblioteki "clang_rt.asan_dynamic-i386.lib"
Używanie narzędzia AddressSanitizer
Rozpocznij tworzenie plików wykonywalnych przy użyciu opcji kompilatora /fsanitize=address
przy użyciu dowolnej z tych typowych metod programowania:
- Kompilacje wiersza polecenia
- System projektu programu Visual Studio
- Integracja narzędzia CMake programu Visual Studio
Ponownie skompiluj, a następnie uruchom program normalnie. To generowanie kodu uwidacznia wiele typów dokładnie zdiagnozowanych usterek. Te błędy są zgłaszane na trzy sposoby: w środowisku IDE debugera, w wierszu polecenia lub przechowywanym w nowym typie pliku zrzutu w celu dokładnego przetwarzania poza wierszem.
Firma Microsoft zaleca używanie narzędzia AddressSanitizer w tych trzech standardowych przepływach pracy:
Pętla wewnętrzna dewelopera
- Visual Studio — wiersz polecenia
- Visual Studio — system projektu
- Visual Studio — CMake
Ciągła integracja/ ciągłe wdrażanie — ciągła integracja/ciągłe programowanie
- Raportowanie błędów — nowe pliki zrzutu narzędzia AddressSanitizer
Rozmycie - budynek z otoki libFuzzer
- Azure OneFuzz
- Komputer lokalny
W tym artykule opisano informacje wymagane do włączenia trzech wymienionych wcześniej przepływów pracy. Informacje są specyficzne dla implementacji systemu Windows 10 (i nowszej) zależnej od platformy narzędzia AddressSanitizer. Ta dokumentacja uzupełnia doskonałą dokumentację firmy Google, Apple i GCC , która została już opublikowana.
Uwaga
Obsługa jest ograniczona do wersji x86 i x64 w systemie Windows 10 lub nowszym. Wyślij nam opinię na temat tego, co chcesz zobaczyć w przyszłych wersjach. Twoja opinia pomaga nam określić priorytety innych urządzeń sanitizer na przyszłość, takich jak /fsanitize=thread
, , /fsanitize=leak
/fsanitize=memory
, , /fsanitize=undefined
lub /fsanitize=hwaddress
. Jeśli wystąpią problemy, możesz zgłosić usterki w tym miejscu .
Używanie narzędzia AddressSanitizer z wiersza polecenia dewelopera
Użyj opcji kompilatora /fsanitize=address
w wierszu polecenia dewelopera, aby włączyć kompilowanie dla środowiska uruchomieniowego AddressSanitizer. Opcja jest zgodna /fsanitize=address
ze wszystkimi istniejącymi poziomami optymalizacji języka C++ lub C (na przykład /Od
, , /O1
/O2
, /O2 /GL
, i PGO
). Opcja działa ze statycznymi i dynamicznymi CTT (na przykład /MD
, , /MT
/MDd
, i /MTd
). Działa niezależnie od tego, czy tworzysz plik EXE, czy bibliotekę DLL. Informacje debugowania są wymagane do optymalnego formatowania stosów wywołań. W poniższym przykładzie cl /fsanitize=address /Zi
jest przekazywany w wierszu polecenia.
Biblioteki AddressSanitizer (pliki lib) są automatycznie połączone. Aby uzyskać więcej informacji, zobacz AddressSanitizer language, build, and debug reference (Informacje o języku AddressSanitizer, kompilacji i debugowaniu).
Przykład — przepełnienie podstawowego buforu globalnego
// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
printf("Hello!\n");
x[100] = 5; // Boom!
return 0;
}
Kompilowanie main.cpp
przy użyciu wiersza polecenia dewelopera dla programu Visual Studio 2019 /fsanitize=address /Zi
Po uruchomieniu wynikowego main.exe
w wierszu polecenia tworzy sformatowany raport o błędach, który następuje poniżej.
Rozważ nakładane, czerwone pola, które podkreślają siedem kluczowych informacji:
W raporcie o błędach znajduje się siedem czerwonych wyróżnień identyfikujących kluczowe elementy informacji. Mapują się na listę numerowaną, która jest zgodna z tym zrzutem ekranu. Pola numerowane podkreślają następujący tekst: 1) global-buffer-overflow 2) ZAPIS o rozmiarze 4 3) basic-global-overflow.cpp 7 4) po prawej stronie zmiennej globalnej "x" zdefiniowanej w "basic-global-overflow.cpp:3:8" 5) o rozmiarze 400 6) 00 00[f9]f9]f9 f9 7) Pole znajduje się w obszarze legendy bajtów cienia i zawiera globalną czerwoną strefę: f9
Czerwone wyróżnienia, od góry do dołu
- Usterka bezpieczeństwa pamięci to przepełnienia globalnego buforu.
- Było 4 bajty (32 bity) przechowywane poza dowolną zmienną zdefiniowaną przez użytkownika.
- Magazyn miał miejsce w funkcji
main()
zdefiniowanej w plikubasic-global-overflow.cpp
w wierszu 7. - Zmienna o nazwie
x
jest definiowana w basic-global-overflow.cpp w wierszu 3, począwszy od kolumny 8 - Ta zmienna
x
globalna ma rozmiar 400 bajtów - Dokładny bajt cienia opisujący adres docelowy magazynu miał wartość
0xf9
- Legenda bajtu cienia mówi
0xf9
, że jest obszarem dopełnienia po prawej stronieint x[100]
Uwaga
Nazwy funkcji w stosie wywołań są generowane za pośrednictwem symbolu LLVM wywoływanego przez środowisko uruchomieniowe po błędzie.
Używanie narzędzia AddressSanitizer w programie Visual Studio
AddressSanitizer jest zintegrowany ze środowiskiem IDE programu Visual Studio. Aby włączyć polecenie AddressSanitizer dla projektu MSBuild, kliknij prawym przyciskiem myszy projekt w Eksplorator rozwiązań i wybierz polecenie Właściwości. W oknie dialogowym Strony właściwości wybierz pozycję Właściwości>konfiguracji C/C++>General, a następnie zmodyfikuj właściwość Enable AddressSanitizer. Wybierz przycisk OK , aby zapisać zmiany.
Aby skompilować z poziomu środowiska IDE, zrezygnuj z wszelkich niezgodnych opcji. W przypadku istniejącego projektu skompilowanego przy użyciu /Od
(lub trybu debugowania) może być konieczne wyłączenie następujących opcji:
- Wyłącz edytowanie i kontynuuj
- Wyłącz
/RTC1
(testy środowiska uruchomieniowego) - Wyłącz
/INCREMENTAL
(łączenie przyrostowe)
Aby skompilować i uruchomić debuger, naciśnij F5. W programie Visual Studio zostanie wyświetlone okno Zgłoszony wyjątek:
Użyj narzędzia AddressSanitizer z poziomu programu Visual Studio: CMake
Aby włączyć narzędzie AddressSanitizer dla projektu CMake utworzonego dla systemu Windows, wykonaj następujące kroki:
Otwórz listę rozwijaną Konfiguracje na pasku narzędzi w górnej części środowiska IDE i wybierz pozycję Zarządzaj konfiguracjami.
Spowoduje to otwarcie edytora ustawień projektu CMake, który odzwierciedla zawartość pliku projektu
CMakeSettings.json
.Wybierz link Edytuj kod JSON w edytorze. To zaznaczenie przełącza widok na nieprzetworzone dane JSON.
Dodaj następujący fragment kodu do
"windows-base"
ustawienia wstępnego, wewnątrz"configurePresets":
, aby włączyć moduł odczyszczący adres:"environment": { "CFLAGS": "/fsanitize=address", "CXXFLAGS": "/fsanitize=address" }
"configurePresets"
wygląda mniej więcej tak:"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" } },
Narzędzie do oczyszczania adresu nie działa, jeśli określono opcję edytuj i kontynuuj (
/ZI
), która jest domyślnie włączona dla nowych projektów CMake. WCMakeLists.txt
pliku oznacz jako komentarz (prefiks z#
) wiersz rozpoczynający się odset(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"
. Wiersz ten wygląda mniej więcej tak:# set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
Wprowadź Ctrl+S , aby zapisać ten plik JSON
Wyczyść katalog pamięci podręcznej CMake i skonfiguruj ponownie, wybierając z menu programu Visual Studio: Project Delete cache (Usuwanie pamięci podręcznej projektu>) i Reconfigure (Ponowne konfigurowanie). Wybierz pozycję Tak , gdy zostanie wyświetlony monit, aby wyczyścić katalog pamięci podręcznej i ponownie skonfigurować.
Zastąp zawartość pliku źródłowego (na przykład
CMakeProject1.cpp
) następującym kodem:// 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; }
Wybierz F5 , aby ponownie skompilować i uruchomić w debugerze.
Ten zrzut ekranu przechwytuje błąd z kompilacji narzędzia CMake.
Zrzuty awaryjne narzędzia AddressSanitizer
Wprowadziliśmy nowe funkcje w narzędziu AddressSanitizer do użycia z przepływami pracy w chmurze i rozproszonymi przepływami pracy. Ta funkcja umożliwia wyświetlanie w trybie offline błędu AddressSanitizer w środowisku IDE. Błąd jest nakładany na źródło, podobnie jak w przypadku sesji debugowania na żywo.
Te nowe pliki zrzutu mogą prowadzić do wydajności podczas analizowania usterki. Nie musisz ponownie uruchamiać ani znajdować zdalnych danych ani wyszukiwać maszyny, która przeszła poza wierszem.
Aby utworzyć nowy typ pliku zrzutu, który można wyświetlić w programie Visual Studio na innym komputerze w późniejszym terminie:
set ASAN_SAVE_DUMPS=MyFileName.dmp
Począwszy od programu Visual Studio 16.9, można wyświetlić dokładnie zdiagnozowany błąd, przechowywany w *.dmp
pliku, na podstawie kodu źródłowego.
Ta nowa funkcja zrzutu awaryjnego umożliwia przepływy pracy oparte na chmurze lub testowanie rozproszone. Może również służyć do tworzenia szczegółowej, możliwej do działania usterki w dowolnym scenariuszu.
Przykładowe błędy
AddressSanitizer może wykryć kilka rodzajów błędów nieprawidłowego użycia pamięci. Poniżej przedstawiono wiele błędów środowiska uruchomieniowego zgłaszanych podczas uruchamiania plików binarnych skompilowanych przy użyciu opcji kompilatora 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
Aby uzyskać więcej informacji na temat przykładów, zobacz AddressSanitizer error examples (Przykłady błędów AddressSanitizer).
Różnice w języku Clang 12.0
Program MSVC obecnie różni się od języka Clang 12.0 w dwóch obszarach funkcjonalnych:
- stack-use-after-scope — to ustawienie jest domyślnie włączone i nie można go wyłączyć.
- stack-use-after-return — ta funkcja wymaga dodatkowej opcji kompilatora i nie jest dostępna tylko przez ustawienie .
ASAN_OPTIONS
Podjęto te decyzje w celu zmniejszenia macierzy testowej wymaganej do dostarczenia tej pierwszej wersji.
Funkcje, które mogą prowadzić do wyników fałszywie dodatnich w programie Visual Studio 2019 16.9, nie zostały uwzględnione. Ta dyscyplina wymuszała efektywną integralność testowania niezbędną podczas rozważania współdziałania z dziesięcioleciami istniejącego kodu. Więcej możliwości można rozważyć w kolejnych wersjach:
- Kolejność inicjowania Fiasko
- Przepełnienie wewnątrz obiektu
- Przepełnienie kontenera
- Odejmowanie wskaźnika/porównanie
Aby uzyskać więcej informacji, zobacz Building for AddressSanitizer with MSVC (Kompilowanie elementu AddressSanitizer za pomocą programu MSVC).
Istniejąca dokumentacja branżowa
Obszerna dokumentacja już istnieje dla tych implementacji języka i platformy technologii AddressSanitizer.
Ten średnik w addressSanitizer (external) opisuje implementację.
Zobacz też
Rozwiązywanie znanych problemów z programemSanitizer
Dokumentacja języka i kompilacji narzędzia AddressSanitizer
AddressSanitizer runtime reference (Dokumentacja środowiska uruchomieniowego AddressSanitizer)
Bajty w tle addressSanitizer
AddressSanitizer — chmura lub testowanie rozproszone
Integracja debugera AddressSanitizer
Przykłady błędów addressSanitizer