AddressSanitizer

Vue d’ensemble

Les langages C et C++ sont puissants, mais peuvent souffrir d’une classe de bogues qui affectent la correction du programme et la sécurité du programme. À partir de Visual Studio 2019 version 16.9, le compilateur Microsoft C/C++ (MSVC) et l’IDE prennent en charge l’outil d’assainissement AddressSanitizer. AddressSanitizer (ASan) est une technologie de compilateur et d’exécution qui expose de nombreux bogues difficiles à trouver avec zéro faux positifs :

Pourquoi utiliser AddressSanitizer

Utilisez AddressSanitizer pour réduire votre temps passé à :

  • Correction fondamentale
  • Portabilité multiplateforme
  • Sécurité
  • Tests de contrainte
  • Intégration de nouveau code

AddressSanitizer, initialement introduit par Google, fournit des technologies de recherche de bogues d’exécution qui utilisent directement vos systèmes de build existants et les ressources de test existantes.

Créer l’intégration et la compatibilité

AddressSanitizer est intégré au système de projet Visual Studio, au système de génération CMake et à l’IDE. Les projets peuvent activer AddressSanitizer en définissant une propriété de projet ou en utilisant une option de compilateur supplémentaire : /fsanitize=address. Cette option est compatible avec tous les niveaux d’optimisation et de configurations de x86 et x64. Toutefois, elle n’est pas compatible avec edit-and-continue, le lien incrémentiel et /RTC.

Prise en charge du vidage sur incident

À compter de Visual Studio 2019 version 16.9, la technologie AddressSanitizer de Microsoft permet l’intégration à l’IDE Visual Studio. La fonctionnalité peut créer un fichier de vidage lorsque le sanitiseur détecte un bogue au moment de l’exécution. Si vous définissez la ASAN_SAVE_DUMPS=MyFileName.dmp variable d’environnement avant d’exécuter votre programme, un fichier de vidage sur incident est créé avec des métadonnées supplémentaires pour un débogage post-mortem efficace des bogues précisément diagnostiqués. Ces fichiers de vidage facilitent l’utilisation étendue de AddressSanitizer pour :

  • Test d’ordinateur local
  • Tests distribués sur site
  • Flux de travail basés sur le cloud pour les tests

Installer AddressSanitizer

Les charges de travail C++ dans Visual Studio Installer installent les bibliothèques AddressSanitizer et l’intégration de l’IDE par défaut. Toutefois, si vous effectuez une mise à niveau à partir d’une version antérieure de Visual Studio 2019, utilisez le programme d’installation pour activer la prise en charge d’ASan après la mise à niveau. Vous pouvez ouvrir le programme d’installation à partir du menu principal Visual Studio en sélectionnant Tools>Get Tools and Features. Choisissez Modify sur votre installation Visual Studio existante à partir du programme d’installation Visual Studio pour accéder à l’écran suivant.

Screenshot montrant le programme d’installation Visual Studio avec le composant AddressSanitizer C++, sous la section Facultative, en surbrillance.

Remarque

Si vous exécutez Visual Studio sur la nouvelle mise à jour, mais que vous n'avez pas installé ASan, vous obtenez une erreur lorsque vous exécutez votre code :

LNK1356 : impossible de trouver la bibliothèque ' clang_rt.asan_dynamic-i386.lib'

Utiliser AddressSanitizer

Commencez à créer vos exécutables avec l'option /fsanitize=address de compilateur à l'aide de l'une de ces méthodes de développement courantes :

  • Compilations en ligne de commande
  • Système de projet Visual Studio
  • Intégration de Visual Studio CMake

Recompilez votre code, puis exécutez votre programme normalement pour exposer de nombreux types de bogues diagnostiqués avec précision. Vous pouvez consulter les problèmes dans le débogueur de l’IDE, la ligne de commande ou le fichier de vidage mémoire.

Microsoft vous recommande d’utiliser AddressSanitizer dans ces trois workflows standard :

Cet article décrit les informations dont vous avez besoin pour activer les trois flux de travail répertoriés précédemment. Les informations sont spécifiques à l’implémentation d'AddressSanitizer dépendante de la plateforme Windows 10 (et versions ultérieures). Cette documentation complète la documentation de Google, Apple et GCC.

Remarque

La prise en charge est limitée à x86 et x64 sur Windows 10 et versions ultérieures. Envoyez-nous des commentaires sur ce que vous souhaitez voir dans les versions ultérieures. Vos commentaires nous aident à hiérarchiser d’autres assainisseurs pour l’avenir, tels que /fsanitize=thread, , /fsanitize=leak/fsanitize=memory, , /fsanitize=undefined, ou /fsanitize=hwaddress. Vous pouvez signaler des bogues ici si vous rencontrez des problèmes.

Utiliser AddressSanitizer à partir d’une invite de commandes développeur

Utilisez l’option /fsanitize=address du compilateur dans une invite de commandes pour développeurs pour activer la compilation pour l'environnement d'exécution AddressSanitizer. L’option /fsanitize=address est compatible avec les niveaux d’optimisation C++ ou C existants, par exemple, /Od, /O1, /O2et /O2 /GL. L’option fonctionne avec des CRT statiques et dynamiques (par exemple, /MD, , /MDd/MTet /MTd). Cela fonctionne si vous créez un EXE ou une DLL. Les informations de débogage sont requises pour une mise en forme optimale des piles d’appels. Dans l’exemple suivant, cl /fsanitize=address /Zi est transmis sur la ligne de commande.

Remarque

AddressSanitizer ne prend pas en charge l’optimisation guidée par profil (PGO). AddressSanitizer ne doit pas être utilisé en production.

Les bibliothèques AddressSanitizer (fichiers .lib) sont liées automatiquement. Pour plus d’informations, consultez la référence sur le langage AddressSanitizer, la génération et le débogage.

Exemple : dépassement de mémoire tampon globale de base

// basic-global-overflow.cpp
#include <stdio.h>
int x[100];
int main() {
    printf("Hello!\n");
    x[100] = 5; // Boom!
    return 0;
}

À l’aide d’une invite de commandes de développeur pour Visual Studio 2019, compilez basic-global-overflow.cpp avec /fsanitize=address /Zi.

Capture d’écran montrant une invite de commandes avec la commande « cl basic-global-overflow.cpp /fsanitize=address /Zi ».

Lorsque vous exécutez le résultat basic-global-overflow.exe sur la ligne de commande, il crée le rapport d’erreurs mis en forme qui suit.

Considérez les boîtes rouges superposées qui mettent en surbrillance sept éléments d’information clés :

Capture d’écran du débogueur montrant une simple erreur de débordement global.

Surbrillances rouges, de haut en bas

  1. Le bogue de sécurité de la mémoire est un dépassement global de mémoire tampon.
  2. Il y avait 4 octets (32 bits) stockés en dehors de toute variable définie par l’utilisateur.
  3. Le stockage a eu lieu dans la fonction main() définie dans le fichier basic-global-overflow.cpp à la ligne 7.
  4. La variable nommée x est définie dans basic-global-overflow.cpp sur la ligne 3, en commençant à la colonne 8.
  5. Cette variable x globale a une taille de 400 octets.
  6. L’octet d’ombre exact décrivant l’adresse ciblée par le magasin avait une valeur .0xf9
  7. La légende des octets fantômes indique que 0xf9 correspond à une zone de remplissage à droite de int x[100].

Remarque

Lorsque AddressSanitizer signale une erreur, le runtime ASan appelle le symbolisateur LLVM pour produire les noms de fonction dans la pile des appels.

Utiliser AddressSanitizer dans Visual Studio

AddressSanitizer est intégré à l’IDE Visual Studio. Pour activer AddressSanitizer pour un projet MSBuild, cliquez avec le bouton droit sur le projet dans Explorateur de solutions et choisissez Propriétés. Dans la Pages de propriétés, sélectionnez Propriétés de configuration>, C/C++>, Général, puis modifiez la propriété Enable AddressSanitizer. Sélectionnez OK pour enregistrer vos modifications.

Capture d’écran de la boîte de dialogue Pages de propriétés montrant la propriété Enable AddressSanitizer.

Pour générer à partir de l’IDE, désactivez les options incompatibles. Pour un projet existant compilé à l’aide /Od (ou mode Débogage), vous devrez peut-être désactiver ces options :

Pour générer et exécuter le débogueur, appuyez sur F5. Une fenêtre d’exception levée s’affiche dans Visual Studio :

Capture d’écran du débogueur montrant une erreur globale de dépassement de mémoire tampon.

Utiliser AddressSanitizer à partir de Visual Studio : CMake

Pour activer AddressSanitizer pour un projet CMake créé pour cibler Windows, procédez comme suit :

  1. Ouvrez le menu déroulant Configurations dans la barre d’outils en haut de l’IDE, puis sélectionnez Gérer les configurations.

    Capture d’écran montrant le menu déroulant de configuration CMake qui affiche des options telles que le débogage x64, la version x64 et, en bas de la liste, Gérer les configurations... est mis en surbrillance.

    Cette action ouvre l'éditeur CMake Project Settings, qui reflète le contenu du fichier CMakeSettings.json de votre project.

  2. Choisissez le lien Modifier JSON . Cette sélection bascule l’affichage en JSON brut.

  3. Pour activer AddressSanitizer, ajoutez l’extrait de code suivant au préréglage "windows-base", à l’intérieur de "configurePresets":.

    "environment": {
      "CFLAGS": "/fsanitize=address",
      "CXXFLAGS": "/fsanitize=address"
    }
    

    "configurePresets" ressemble à ceci ensuite :

        "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. AddressSanitizer ne fonctionne pas si edit-and-continue est spécifié (/ZI), qui est activé par défaut pour les nouveaux projets CMake. Dans CMakeLists.txt, commentez (préfixe avec #) la ligne qui commence par set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT". Cette ligne ressemble à ceci :

    # 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. Utilisez Ctrl+S pour enregistrer ce fichier JSON.

  6. Effacez votre répertoire de cache CMake et reconfigurez en choisissant dans le menu Visual Studio : Supprimer le cache et reconfigurer du projet>. Choisissez Oui lorsque l’invite s’affiche pour effacer votre répertoire de cache et reconfigurer.

  7. Remplacez le contenu du fichier source, par exemple, CMakeProject1.cpppar le code suivant :

    // 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. Choisissez F5 pour recompiler et exécuter sous le débogueur.

    Cette capture d’écran montre l’erreur de la construction CMake.

    Capture d’écran montrant une exception indiquant : Address Sanitizer Error : Global buffer overflow.

Vidages de mémoire AddressSanitizer

AddressSanitizer inclut des fonctionnalités à utiliser avec des flux de travail cloud et distribués. Cette fonctionnalité permet l’affichage hors connexion d’une erreur AddressSanitizer dans l’IDE. L’erreur est superposée sur votre source, tout comme vous le feriez dans une session de débogage en direct.

Ces fichiers de vidage peuvent entraîner des gains d’efficacité lorsque vous analysez un bogue. Vous n’avez pas besoin de réexécuter, de rechercher des données distantes ou de rechercher une machine hors connexion.

Pour produire un fichier de vidage que vous pouvez afficher dans Visual Studio sur un autre ordinateur à une date ultérieure :

set ASAN_SAVE_DUMPS=MyFileName.dmp

À partir de Visual Studio 16.9, vous pouvez afficher a erreur diagnostiqué avec précision, stockée dans votre fichier *.dmp, en plus de votre code source.

Cette fonctionnalité de vidage sur incident permet des workflows basés sur le cloud ou des tests distribués. Il peut également être utilisé pour enregistrer un bogue détaillé et actionnable dans n’importe quel scénario.

Exemples d’erreurs

AddressSanitizer peut détecter plusieurs types d’erreurs d’utilisation incorrecte de la mémoire. Voici la plupart des erreurs d’exécution signalées lorsque vous exécutez vos fichiers binaires compilés à l’aide de l’option du compilateur AddressSanitizer (/fsanitize=address) :

Pour plus d’informations sur les exemples, consultez les exemples d’erreur AddressSanitizer.

Différences avec Clang 12.0

MSVC diffère actuellement de Clang 12.0 dans deux domaines fonctionnels :

  • stack-use-after-scope : ce paramètre est activé par défaut et ne peut pas être désactivé.
  • stack-use-after-return : cette fonctionnalité nécessite une option de compilateur supplémentaire et n’est pas disponible uniquement en définissant ASAN_OPTIONS.

Ces décisions ont été prises pour réduire la matrice de test nécessaire pour fournir cette première version.

Les fonctionnalités susceptibles d’entraîner des faux positifs dans Visual Studio 2019 16.9 n’ont pas été incluses. Cette discipline a imposé une intégrité de test efficace nécessaire lorsque l'on considère l'interopérabilité avec plusieurs décennies de code existant. D’autres fonctionnalités peuvent être prises en compte dans les versions ultérieures :

Pour plus d’informations, consultez Building for AddressSanitizer avec MSVC.

Documentation du secteur

Une documentation complète existe pour ces implémentations dépendantes de la langue et de la plateforme de la technologie AddressSanitizer.

Ce document séminal sur l'AddressSanitizer (externe) décrit l’implémentation.

Voir aussi