AddressSanitizer
Omówienie
Języki C & ++ są zaawansowane, ale mogą cierpieć na klasę 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ługują sanitizer AddressSanitizer . AddressSanitizer (ASan) to technologia kompilatora i środowiska uruchomieniowego, która uwidacznia wiele trudnych do znalezienia usterek 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- Podwójna bezpłatna i bezpłatna
- Przepełnienie zmiennej globalnej
- Przepełnienie buforu stertowego
- Nieprawidłowe wyrównanie wyrównanych wartości
memcpy
istrncat
nakładanie się parametrów- Przepełnienie i niedopełnieniebuforu stosu
- Użycie stosu po
return
i użyj po zakresie - Użycie pamięci po zatruciem
Użyj narzędzia AddressSanitizer, aby skrócić czas spędzony na:
- Poprawność podstawowa
- Przenośność międzyplatformowa
- Zabezpieczenia
- Testowanie warunków skrajnych
- Integrowanie nowego kodu
AddressSanitizer, pierwotnie wprowadzony przez firmę Google, zapewnia technologie znajdowania błędów w czasie wykonywania, które używają istniejących systemów kompilacji i istniejących zasobów testowych bezpośrednio.
Narzędzie AddressSanitizer jest zintegrowane z systemem projektu programu Visual Studio, systemem kompilacji CMake i środowiskiem IDE. Projekty mogą włączyć właściwość 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ę z środowiskiem IDE programu Visual Studio. Funkcje mogą opcjonalnie utworzyć plik zrzutu awaryjnego, gdy sanitizer wykryje 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 dokładnie zdiagnozowanych usterek. Te pliki zrzutu ułatwiają rozszerzone korzystanie z narzędzia AddressSanitizer:
- Testowanie maszyn lokalnych,
- Lokalne testowanie rozproszone i
- Przepływy pracy oparte na chmurze do 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ę usługi ASan po uaktualnieniu:
Możesz wybrać pozycję Modyfikuj w istniejącej instalacji programu Visual Studio z Instalator programu Visual Studio, aby przejść do powyższego ekranu.
Uwaga
Jeśli uruchomisz program Visual Studio w nowej aktualizacji, ale nie zainstalowano rozwiązania ASan, podczas uruchamiania kodu zostanie wyświetlony błąd:
LNK1356: nie można odnaleźć biblioteki "clang_rt.asan_dynamic-i386.lib"
Korzystanie z narzędzia AddressSanitizer
Rozpocznij tworzenie plików wykonywalnych za pomocą opcji kompilatora /fsanitize=address
przy użyciu dowolnej z tych typowych metod programowania:
- Kompilacje wiersza polecenia
- System projektu programu Visual Studio
- Integracja programu Visual Studio CMake
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 na potrzeby precyzyjnego przetwarzania poza wierszem.
Firma Microsoft zaleca używanie klasy 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 addressSanitizer
Rozmycie - budowanie z otoki libFuzzer
- Azure OneFuzz
- Maszyna lokalna
W tym artykule opisano informacje wymagane do włączenia trzech przepływów pracy wymienionych powyżej. Informacje są specyficzne dla Windows 10 platformy implementacji AddressSanitizer. Ta dokumentacja uzupełnia doskonałą dokumentację firmy Google, Apple i GCC już opublikowaną.
Uwaga
Bieżąca obsługa jest ograniczona do wersji x86 i x64 w Windows 10. Wyślij nam opinię na temat tego, co chcesz zobaczyć w przyszłych wersjach. Twoja opinia pomaga nam określić priorytety innych sanitizerów w przyszłości, takich jak /fsanitize=thread
, , /fsanitize=leak
, /fsanitize=memory
, /fsanitize=undefined
lub /fsanitize=hwaddress
. W tym miejscu możesz zgłaszać błędy , jeśli wystąpią problemy.
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
). Ta opcja działa z statycznymi i dynamicznymi punktami CTS (na przykład /MD
, , /MDd
/MT
, i /MTd
). Działa to 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 cl /fsanitize=address /Zi
przykładzie 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 (Dokumentacja dotycząca języka AddressSanitizer, kompilacji i debugowania).
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 dla deweloperów dla programu Visual Studio 2019 /fsanitize=address /Zi
Po uruchomieniu wynikowego main.exe
w wierszu polecenia tworzy sformatowany raport o błędach widoczny poniżej.
Rozważ nakładane czerwone pola, które podkreślają siedem kluczowych informacji:
Czerwone wyróżnienia, od góry do dołu
- Usterka bezpieczeństwa pamięci to przepełnienie buforu globalnego.
- Nie było 4 bajtów (32 bitów) przechowywanych 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 pliku basic-global-overflow.cpp w wierszu 3, zaczynając od kolumny 8 - Ta zmienna globalna
x
ma rozmiar 400 bajtów - Dokładny bajt cienia opisujący adres docelowy sklepu miał wartość
0xf9
- Legenda bajtu cienia mówi
0xf9
, że jest obszarem dopełniania po prawej stronieint x[100]
Uwaga
Nazwy funkcji w stosie wywołań są tworzone 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 z ś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> konfiguracjiC/C++>General, a następnie zmodyfikuj właściwość Enable AddressSanitizer. Wybierz przycisk OK , aby zapisać zmiany.
Aby skompilować środowisko 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 edycję i kontynuuj
- Wyłącz
/RTC1
(testy środowiska uruchomieniowego) /INCREMENTAL
Wyłącz (łączenie przyrostowe)
Aby skompilować i uruchomić debuger, wprowadź klawisz F5. To okno zostanie wyświetlone w programie Visual Studio:
Use AddressSanitizer from Visual Studio: CMake
Aby włączyć narzędzie AddressSanitizer dla projektu CMake utworzonego na potrzeby 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.
Ten wybór otwiera edytor ustawień projektu CMake, który jest zapisywany w pliku CMakeSettings.json.
Wybierz link Edytuj kod JSON w edytorze. To zaznaczenie powoduje przełączenie widoku na nieprzetworzone dane JSON.
Dodaj właściwość: "addressSanitizerEnabled": true
Ten obraz jest plikiem CMakeSettings.json po tej zmianie:
Wprowadź klawisze Ctrl+S , aby zapisać ten plik JSON, a następnie wprowadź klawisz 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 wierzchu źródła, tak jak w przypadku sesji debugowania na żywo.
Te nowe pliki zrzutu mogą prowadzić do zwiększenia wydajności podczas analizowania usterki. Nie musisz ponownie uruchamiać ani znajdować zdalnych danych ani szukać maszyny, która przeszła poza linią.
Aby utworzyć nowy typ pliku zrzutu, który można wyświetlić w programie Visual Studio na innej maszynie 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 wykonywanie przepływów pracy opartych na chmurze lub testowanie rozproszone. Można go również użyć do utworzenia szczegółowej, możliwej do wykonania akcji usterki w dowolnym scenariuszu.
Przykładowe błędy
Rozwiązanie 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 Przykłady błędów AddressSanitizer.
Różnice w języku Clang 12.0
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 testów wymaganej do dostarczenia tej pierwszej wersji.
Nie uwzględniono funkcji, które mogą prowadzić do fałszywie dodatnich wyników w programie Visual Studio 2019 16.9. 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:
- Inicjowanie zamówienia Fiasco
- Przepełnienie wewnątrz obiektu
- Kontener Overflow
- Odejmowanie wskaźnika/porównanie
Aby uzyskać więcej informacji, zobacz Building for AddressSanitizer with MSVC (Kompilowanie elementu AddressSanitizer za pomocą MSVC).
Istniejąca dokumentacja branżowa
Obszerna dokumentacja już istnieje dla tych implementacji językowych i zależnych od platformy technologii AddressSanitizer.
Ten średnikowy dokument w module AddressSanitizer opisuje implementację.
Zobacz też
Rozwiązywanie znanych problemów z rozwiązaniemSanitizer
Dokumentacja kompilatora AddressSanitizer i języka
Dokumentacja środowiska uruchomieniowego addressSanitizer
Bajty cieni addressSanitizer
AddressSanitizer — chmura lub testowanie rozproszone
Integracja debugera AddressSanitizer
Przykłady błędów addressSanitizer