Partager via


Runtime AddressSanitizer

La bibliothèque d’exécution AddressSanitizer intercepte les fonctions et opérations courantes d’allocation de mémoire pour permettre l’inspection des accès à la mémoire. Il existe plusieurs bibliothèques d’exécution qui prennent en charge les différents types d’exécutables que le compilateur peut générer. Le compilateur et l’éditeur de liens lient automatiquement les bibliothèques d’exécution appropriées, tant que vous passez l’option au moment de la /fsanitize=address compilation. Vous pouvez remplacer le comportement par défaut à l’aide de l’option au moment du /NODEFAULTLIB lien. Pour plus d’informations, consultez la section relative à la liaison dans le langage AddressSanitizer, la génération et la référence de débogage.

Lors de la compilation avec cl /fsanitize=address, le compilateur génère des instructions pour gérer et vérifier les octets instantanés. Votre programme utilise cette instrumentation pour vérifier les accès à la mémoire sur la pile, dans le tas ou dans l’étendue globale. Le compilateur produit également des métadonnées décrivant la pile et les variables globales. Ces métadonnées permettent au runtime de générer des diagnostics d’erreurs précis : noms de fonction, lignes et colonnes dans votre code source. Combiné, les vérifications du compilateur et les bibliothèques d’exécution peuvent diagnostiquer précisément de nombreux types de bogues de sécurité de la mémoire s’ils sont rencontrés au moment de l’exécution.

La liste des bibliothèques d’exécution pour la liaison au runtime AddressSanitizer, à partir de Visual Studio 17.7 Preview 3, suit. Pour plus d’informations sur les /MT options (lier statiquement le runtime) et /MD (lier dynamiquement le redist au moment de l’exécution), consultez /MD, /MT, /LD (Utiliser la bibliothèque d’exécution) .

Remarque

Dans le tableau suivant, {arch} est soit i386 .x86_64 Ces bibliothèques utilisent des conventions Clang pour les noms d’architecture. Les conventions MSVC sont normalement x86 et x64 plutôt que i386 et x86_64, mais elles font référence aux mêmes architectures.

Option CRT Bibliothèque runtime AddressSanitizer (.lib) Binaire du runtime d’adresse (.dll)
/MT ou /MTd clang_rt.asan_dynamic-{arch}, clang_rt.asan_static_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MD ou /MDd clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}

Le diagramme suivant montre comment les bibliothèques du runtime de langage sont liées pour les options de /MTdcompilateur , /MDet /MDd les options du /MTcompilateur :

Diagramme de la façon dont les bibliothèques runtime sont liées pour différentes options du compilateur.

L’image montre trois scénarios de liaison de la bibliothèque runtime. Le premier est /MT ou /MTd. My_exe.exe et my_dll.dll sont tous deux affichés avec leurs propres copies des runtimes VCRuntime, CRT universels et C++liés statiquement. Les scénarios montrent /MD dans lesquels my_exe.exe et my_dll.dll partager vcruntime140.dll, ucrtbase.dll et msvcp140.dll. Le dernier scénario montre /MDd dans lequel my_exe.exe et my_dll.dll partager les versions de débogage des runtimes : vcruntime140d.dll, ucrtbased.dll et msvcp140d.dll

Le diagramme suivant montre comment la bibliothèque ASan est liée pour différentes options du compilateur :

Diagramme de la façon dont la dll d’exécution ASan est liée.

L’image montre quatre scénarios de liaison de la bibliothèque d’exécution ASan. Les scénarios concernent /MT (lier statiquement le runtime), /MTd (lier statiquement le runtime de débogage), /MD (lier dynamiquement le redist au moment de l’exécution), /MDd (lier dynamiquement le redist au moment de l’exécution). Dans tous les cas, my_exe.exe liens et ses associés my_dll.dll lien vers une instance unique de clang-rt.asan-dynamix-x86_64.dll.

Même lorsque vous liez statiquement, la DLL du runtime ASan doit être présente au moment de l’exécution, contrairement à d’autres composants C Runtime.

Versions précédentes

Avant Visual Studio 17.7 Preview 3, les builds liées statiquement (/MT ou /MTd) n’utilisaient pas de dépendance DLL. Au lieu de cela, le runtime AddressSanitizer était lié statiquement à l’EXE de l’utilisateur. Les projets DLL chargent ensuite les exportations à partir de l’EXE de l’utilisateur pour accéder aux fonctionnalités ASan.

Les projets liés dynamiquement (/MD ou /MDd) ont utilisé différentes bibliothèques et DLL selon que le projet a été configuré pour le débogage ou la mise en production. Pour plus d’informations sur ces modifications et leurs motivations, consultez MSVC Address Sanitizer – One DLL for all Runtime Configurations.

Le tableau suivant décrit le comportement précédent de la liaison de bibliothèque d’exécution AddressSanitizer, avant Visual Studio 17.7 Preview 3 :

Option CRT DLL ou EXE DÉBOGUER? Bibliothèque ASan (.lib) Binaire du runtime ASan (.dll)
/MT EXE Non clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} Aucun(e)
/MT DLL Non clang_rt.asan_dll_thunk-{arch} Aucun(e)
/MD Soit Non clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} clang_rt.asan_dynamic-{arch}
/MT EXE Oui clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} Aucun(e)
/MT DLL Oui clang_rt.asan_dbg_dll_thunk-{arch} Aucun(e)
/MD Vous pouvez soit utiliser Oui clang_rt.asan_dbg_dynamic-{arch}, clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} clang_rt.asan_dbg_dynamic-{arch}

Le diagramme suivant montre comment la bibliothèque ASan a été liée pour différentes options du compilateur avant Visual Studio 2022 17.7 Preview 3 :

Diagramme montrant comment la dll du runtime ASan a été liée avant Visual Studio 2022 Preview 3.

L’image montre quatre scénarios de liaison de la bibliothèque d’exécution ASan. Les scénarios concernent /MT (lier statiquement le runtime), /MTd (lier statiquement le runtime de débogage), /MD (lier dynamiquement le redist au moment de l’exécution), /MDd (lier dynamiquement le redist au moment de l’exécution). Pour /MT, my_exe.exe a une copie liée statiquement du runtime ASan. my_dll.dll liens vers le runtime ASan dans my_exe.exe. Pour /MTd, le diagramme est le même, sauf qu’il utilise le runtime ASan lié de manière statique. Pour /MD, my_exe.exe et my_dll.dll lien vers le runtime ASan lié dynamiquement nommé clang_rt.asan_dynamic-x86_64.dll. Pour /MDd, le diagramme est le même, sauf my_exe.exe et my_dll.dll lien vers le runtime ASan de débogage nommé clang_rt.asan_dbg_dynamic-x86_64.dll.

Interception de fonction

AddressSanitizer obtient l’interception de fonction par le biais de nombreuses techniques de mise à chaud. Ces techniques sont mieux documentées dans le code source lui-même.

Les bibliothèques runtime interceptent de nombreuses fonctions courantes de gestion de la mémoire et de manipulation de la mémoire. Pour obtenir une liste, consultez la liste AddressSanitizer des fonctions interceptées. Les intercepteurs d’allocation gèrent les métadonnées et les octets d’ombre liés à chaque appel d’allocation. Chaque fois qu’une fonction CRT telle que malloc ou delete est appelée, les intercepteurs définissent des valeurs spécifiques dans la région de mémoire fantôme AddressSanitizer pour indiquer si ces emplacements de tas sont actuellement accessibles et quelles sont les limites de l’allocation. Ces octets d’ombre permettent aux vérifications générées par le compilateur des octets d’ombre de déterminer si une charge ou un magasin est valide.

L’interception n’est pas garantie de réussir. Si un prologue de fonction est trop court pour jmp être écrit, l’interception peut échouer. Si une défaillance d’interception se produit, le programme lève un debugbreak et s’arrête. Si vous attachez un débogueur, la cause du problème d’interception est claire. Si vous rencontrez ce problème, signalez un bogue.

Remarque

Les utilisateurs peuvent éventuellement tenter de continuer après une interception ayant échoué en définissant la variable ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE d’environnement sur n’importe quelle valeur. La poursuite d’un échec d’interception peut entraîner des rapports de bogues manqués pour cette fonction.

Allocators personnalisés et runtime AddressSanitizer

Le runtime AddressSanitizer fournit des intercepteurs pour les interfaces allocator courantes, mallocfree/,/newdelete (/HeapFreeHeapAllocvia ).RtlAllocateHeap/RtlFreeHeap De nombreux programmes utilisent des allocateurs personnalisés pour une raison ou une autre, un exemple serait n’importe quel programme utilisant dlmalloc ou une solution à l’aide de l’interface std::allocator et VirtualAlloc(). Le compilateur ne peut pas ajouter automatiquement des appels de gestion de la mémoire fantôme à un allocateur personnalisé. Il incombe à l’utilisateur d’utiliser l’interface d’empoisonnement manuelle fournie. Cette API permet à ces allocators de fonctionner correctement avec le runtime AddressSanitizer existant et les conventions d’octets d’ombre.

Interface d’empoisonnement de AddressSanitizer manuelle

L’interface d’éclairage est simple, mais elle impose des restrictions d’alignement à l’utilisateur. Les utilisateurs peuvent importer ces prototypes en important sanitizer/asan_interface.h. Voici les prototypes de fonction d’interface :

void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

Pour plus de commodité, le fichier d’en-tête de l’interface AddressSanitizer fournit des macros wrapper. Ces macros vérifient si la fonctionnalité AddressSanitizer est activée pendant la compilation. Ils permettent à votre code source d’omettre les appels de fonction d’empoisonnement lorsqu’ils ne sont pas nécessaires. Ces macros doivent être préférées par rapport à l’appel des fonctions ci-dessus directement :

#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)

Exigences d’alignement pour l’empoisonnement de AddressSanitizer

Tout empoisonnement manuel des octets d’ombre doit prendre en compte les exigences d’alignement. L’utilisateur doit ajouter un remplissage si nécessaire afin que les octets d’ombre se terminent sur une limite d’octets dans la mémoire de l’ombre. Chaque bit de la mémoire fantôme AddressSanitizer encode l’état d’un octet unique dans la mémoire de l’application. Cet encodage signifie que la taille totale de chaque allocation, y compris tout remplissage, doit être alignée sur une limite de 8 octets. Si l’exigence d’alignement n’est pas satisfaite, cela peut entraîner des rapports de bogues incorrects. Les rapports incorrects peuvent se manifester comme des rapports manquants (faux négatifs) ou des rapports sur des non-erreurs (faux positifs).

Pour obtenir une illustration de l’exigence d’alignement et des problèmes potentiels, consultez les exemples d’alignement ASan fournis. Il s’agit d’un petit programme pour montrer ce qui peut se tromper avec l’empoisonnement manuel de la mémoire de l’ombre. La seconde est un exemple d’empoisonnement manuel à l’aide de l’interface std::allocator .

Options d’exécution

Microsoft C/C++ (MSVC) utilise un runtime basé sur le runtime Clang AddressSanitizer à partir du référentiel llvm-project. En raison de cela, la plupart des options d’exécution sont partagées entre les deux versions. Une liste complète des options d’exécution Clang publiques est disponible ici. Nous documentons certaines différences dans les sections qui suivent. Si vous découvrez des options qui ne fonctionnent pas comme prévu, signalez un bogue.

Options AddressSanitizer non prises en charge

  • detect_container_overflow
  • unmap_shadow_on_exit

Remarque

L’option halt_on_error d’exécution AddressSanitizer ne fonctionne pas comme prévu. Dans les bibliothèques runtime Clang et MSVC, de nombreux types d’erreurs sont considérés comme non continuables, y compris la plupart des erreurs d’altération de la mémoire.

Pour plus d’informations, consultez la section Différences avec Clang 12.0 .

Options d’exécution AddressSanitizer spécifiques à MSVC

  • windows_hook_legacy_allocatorsBoolean, défini pour false désactiver l’interception des LocalAlloc GlobalAlloc et des allocateurs.

    Remarque

    L’option windows_hook_legacy_allocators n’était pas disponible dans le runtime du projet llvm public lors de l’écriture de cet article. L’option peut éventuellement être renvoyée au projet public ; toutefois, elle dépend de la révision du code et de l’acceptation de la communauté.

    L’option windows_hook_rtl_allocators, précédemment une fonctionnalité d’opt-in alors que AddressSanitizer était expérimental, est désormais activée par défaut. Dans les versions antérieures à Visual Studio 2022 version 17.4.6, la valeur d’option par défaut est false. Dans Visual Studio 2022 version 17.4.6 et versions ultérieurestrue, l’option windows_hook_rtl_allocators est par défaut .

  • iat_overwrite Chaîne définie "error" par défaut. D’autres valeurs possibles sont "protect" et "ignore". Certains modules peuvent remplacer les import address table autres modules pour personnaliser les implémentations de certaines fonctions. Par exemple, les pilotes fournissent généralement des implémentations personnalisées pour un matériel spécifique. L’option iat_overwrite gère la protection du runtime AddressSanitizer contre les remplacements pour des fonctions spécifiques memoryapi.h . Le runtime effectue actuellement le suivi des fonctions et VirtualProtectVirtualQuery des fonctions pour la VirtualAllocprotection. Cette option est disponible dans Visual Studio 2022 version 17.5 Preview 1 et versions ultérieures. Les valeurs suivantes iat_overwrite contrôlent la façon dont le runtime réagit lorsque les fonctions protégées sont remplacées :

    • S’il est défini "error" sur (valeur par défaut), le runtime signale une erreur chaque fois qu’un remplacement est détecté.
    • Si la valeur est définie "protect", le runtime tente d’éviter d’utiliser la définition remplacée et de continuer. En fait, la définition d’origine memoryapi de la fonction est utilisée à partir de l’intérieur du runtime pour éviter une récursivité infinie. Les autres modules du processus utilisent toujours la définition remplacée.
    • Si la valeur est définie "ignore", le runtime ne tente pas de corriger les fonctions remplacées et passe à l’exécution.
  • windows_fast_fail_on_error Boolean (false par défaut), défini pour true permettre au processus de se terminer par un __fastfail(71) après l’impression du rapport d’erreurs.

Remarque

Lorsque abort_on_error valeur est définie sur true, sur Windows, le programme se termine par une sortie(3). Pour ne pas modifier le comportement actuel, nous avons décidé d’introduire cette nouvelle option à la place. Si les deux abort_on_error et windows_fast_fail_on_error sont vraies, le programme s’arrête avec le __fastfail.

Liste AddressSanitizer des fonctions interceptées (Windows)

Le runtime AddressSanitizer active de nombreuses fonctions pour activer les vérifications de sécurité de la mémoire au moment de l’exécution. Voici une liste non exhaustive des fonctions que le runtime AddressSanitizer surveille.

Intercepteurs par défaut

Intercepteurs facultatifs

Les intercepteurs répertoriés ici sont installés uniquement lorsqu’une option d’exécution AddressSanitizer est activée. Définissez cette option windows_hook_legacy_allocators pour false désactiver l’interception de l’allocateur hérité. set ASAN_OPTIONS=windows_hook_legacy_allocators=false

Voir aussi

Vue d’ensemble de AddressSanitizer
Résoudre les problèmes connus liés à AddressSanitizer
Référence de build et de langage AddressSanitizer
Octets d’ombre AddressSanitizer
Test cloud ou distribué AddressSanitizer
Intégration du débogueur AddressSanitizer
Exemples d’erreur AddressSanitizer