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:

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.

Screenshot of the Visual Studio Installer. The C++ AddressSanitizer component, under the Optional section, is highlighted.

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:

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 zależnej od platformy AddressSanitizer. Ta dokumentacja uzupełnia doskonałą dokumentację firmy Google, Apple i GCC , która została już opublikowana.

Uwaga

Bieżąca obsługa jest ograniczona do wersji x86 i x64 w systemie Windows 10. 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=undefinedlub /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

Screenshot of a command prompt showing the command to compile with AddressSanitizer options. The command is: `cl main.cpp -faanitize-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:

Screenshot of the debugger showing a basic global overflow error.

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) WRITE o rozmiarze 4 3) basic-global-overflow.cpp 7 4) po prawej stronie zmiennej globalnej "x" zdefiniowanej w parametrze "basic-global-global-overflow". overflow.cpp:3:8' 5) o rozmiarze 400 6) 00 00[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

  1. Usterka bezpieczeństwa pamięci to przepełnienia globalnego buforu.
  2. Było 4 bajty (32 bity) przechowywane 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 x globalna ma rozmiar 400 bajtów
  6. Dokładny bajt cienia opisujący adres docelowy magazynu miał wartość 0xf9
  7. Legenda bajtu cienia mówi 0xf9 , że jest obszarem dopełnienia po prawej stronie int 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.

Screenshot of the Property Pages dialog showing the Enable AddressSanitizer property.

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:

Aby skompilować i uruchomić debuger, naciśnij klawisz F5. W programie Visual Studio zostanie wyświetlone okno Zgłoszony wyjątek:

Screenshot of the debugger showing a global buffer overflow error.

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:

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

    Screenshot of the CMake configuration dropdown. It displays options like x64 Debug, x64 Release, and so on. At the bottom of the list, Manage Configurations... is highlighted.

    Spowoduje to otwarcie edytora Ustawienia projektu CMake, który odzwierciedla zawartość pliku projektuCMakeSettings.json.

  2. Wybierz link Edytuj kod JSON w edytorze. To zaznaczenie przełącza widok na nieprzetworzone dane JSON.

  3. 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"
            }
          },
    
  4. 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. W CMakeLists.txtpliku oznacz jako komentarz (prefiks z #) wiersz rozpoczynający się od set(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>>")
    
  5. Wprowadź klawisze Ctrl+S , aby zapisać ten plik JSON

  6. 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ć.

  7. 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;
    }
    
  8. Wybierz klawisz F5 , aby ponownie skompilować i uruchomić w debugerze.

    Ten zrzut ekranu przechwytuje błąd z kompilacji narzędzia CMake.

    Screenshot of an exception that says: Address Sanitizer Error: Global buffer overflow. In the background, address sanitizer output is visible in command window.

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):

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:

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