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 /MTd
compilateur , /MD
et /MDd
les options du /MT
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 :
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} |
Aucune |
/MT |
DLL | Non | clang_rt.asan_dll_thunk-{arch} |
Aucune |
/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} |
Aucune |
/MT |
DLL | Oui | clang_rt.asan_dbg_dll_thunk-{arch} |
Aucune |
/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 :
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, malloc
free
/,/new
delete
(/HeapFree
HeapAlloc
via ).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_allocators
Boolean, défini pourfalse
désactiver l’interception desLocalAlloc
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 estfalse
. Dans Visual Studio 2022 version 17.4.6 et versions ultérieurestrue
, l’optionwindows_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 lesimport 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’optioniat_overwrite
gère la protection du runtime AddressSanitizer contre les remplacements pour des fonctions spécifiquesmemoryapi.h
. Le runtime effectue actuellement le suivi des fonctions etVirtualProtect
VirtualQuery
des fonctions pour laVirtualAlloc
protection. Cette option est disponible dans Visual Studio 2022 version 17.5 Preview 1 et versions ultérieures. Les valeurs suivantesiat_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’originememoryapi
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.
- S’il est défini
windows_fast_fail_on_error
Boolean (false par défaut), défini pourtrue
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
__C_specific_handler
(x64 uniquement)_aligned_free
_aligned_malloc
_aligned_msize
_aligned_realloc
_calloc_base
_calloc_crt
_calloc_dbg
(débogage du runtime uniquement)_except_handler3
(x86 uniquement)_except_handler4
(x86 uniquement) (non documenté)_expand
_expand_base
(non documenté)_expand_dbg
(débogage du runtime uniquement)_free_base
(non documenté)_free_dbg
(débogage du runtime uniquement)_malloc_base
(non documenté)_malloc_crt
(non documenté)_malloc_dbg
(débogage du runtime uniquement)_msize
_msize_base
(non documenté)_msize_dbg
(débogage du runtime uniquement)_realloc_base
(non documenté)_realloc_crt
(non documenté)_realloc_dbg
(débogage du runtime uniquement)_recalloc
_recalloc_base
(non documenté)_recalloc_crt
(non documenté)_recalloc_dbg
(débogage du runtime uniquement)_strdup
atoi
atol
calloc
CreateThread
free
frexp
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
RaiseException
realloc
RtlAllocateHeap
RtlCreateHeap
RtlDestroyHeap
RtlFreeHeap
RtlRaiseException
RtlReAllocateHeap
(non documenté)RtlSizeHeap
(non documenté)SetUnhandledExceptionFilter
strcat
strchr
strcmp
strcpy
strcspn
strdup
strlen
strncat
strncmp
strncpy
strnlen
strpbrk
strspn
strstr
strtok
strtol
wcslen
wcsnlen
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
GlobalAlloc
GlobalFree
GlobalHandle
GlobalLock
GlobalReAlloc
GlobalSize
GlobalUnlock
LocalAlloc
LocalFree
LocalHandle
LocalLock
LocalReAlloc
LocalSize
LocalUnlock
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