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:

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:

Instalator programu Visual Studio zrzut ekranu z wyróżnionym składnikiem C++ AddressSanitizer

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:

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=undefinedlub /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 /GLi 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

Zrzut ekranu wiersza polecenia przedstawiający polecenie do skompilowania za pomocą opcji AddressSanitizer.

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:

Zrzut ekranu przedstawiający debuger przedstawiający podstawowy błąd przepełnienia globalnego.

Czerwone wyróżnienia, od góry do dołu

  1. Usterka bezpieczeństwa pamięci to przepełnienie buforu globalnego.
  2. Nie było 4 bajtów (32 bitów) przechowywanych poza dowolną zmienną zdefiniowaną przez użytkownika.
  3. Magazyn miał miejsce w funkcji main() zdefiniowanej w pliku basic-global-overflow.cpp w wierszu 7.
  4. Zmienna o nazwie x jest definiowana w pliku basic-global-overflow.cpp w wierszu 3, zaczynając od kolumny 8
  5. Ta zmienna globalna x ma rozmiar 400 bajtów
  6. Dokładny bajt cienia opisujący adres docelowy sklepu miał wartość 0xf9
  7. Legenda bajtu cienia mówi 0xf9 , że jest obszarem dopełniania po prawej stronie int 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.

Zrzut ekranu przedstawiający okno dialogowe Strony właściwości z właściwością Enable AddressSanitizer.

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:

Aby skompilować i uruchomić debuger, wprowadź klawisz F5. To okno zostanie wyświetlone w programie Visual Studio:

Zrzut ekranu przedstawiający debuger przedstawiający błąd przepełnienia buforu globalnego.

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:

  1. Otwórz listę rozwijaną Konfiguracje na pasku narzędzi w górnej części środowiska IDE i wybierz pozycję Zarządzaj konfiguracjami.

    Zrzut ekranu przedstawiający listę rozwijaną konfiguracji narzędzia CMake.

    Ten wybór otwiera edytor ustawień projektu CMake, który jest zapisywany w pliku CMakeSettings.json.

  2. Wybierz link Edytuj kod JSON w edytorze. To zaznaczenie powoduje przełączenie widoku na nieprzetworzone dane JSON.

  3. Dodaj właściwość: "addressSanitizerEnabled": true

    Ten obraz jest plikiem CMakeSettings.json po tej zmianie:

    Zrzut ekranu przedstawiający widok edytora tekstów pliku CMakeSettings.json.

  4. 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.

Zrzut ekranu przedstawiający komunikat o błędzie 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):

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:

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