AddressSanitizer-Laufzeit
Die AddressSanitizer-Laufzeitbibliothek fängt allgemeine Speicherzuweisungsfunktionen und -vorgänge ab, um die Überprüfung von Speicherzugriffen zu ermöglichen. Es gibt mehrere verschiedene Laufzeitbibliotheken, die die verschiedenen Typen von ausführbaren Dateien unterstützen, die der Compiler generieren kann. Der Compiler und Linker verknüpfen automatisch die entsprechenden Laufzeitbibliotheken, solange Sie die /fsanitize=address
Option zur Kompilierungszeit übergeben. Sie können das Standardverhalten überschreiben, indem Sie die /NODEFAULTLIB
Option zur Linkzeit verwenden. Weitere Informationen finden Sie im Abschnitt zum Verknüpfen in der AddressSanitizer-Sprache, im Build- und Debugging-Verweis.
Beim Kompilieren mit cl /fsanitize=address
dem Compiler werden Anweisungen zum Verwalten und Überprüfen von Schattenbytes generiert. Ihr Programm verwendet diese Instrumentierung, um Speicherzugriffe auf den Stapel, im Heap oder im globalen Bereich zu überprüfen. Der Compiler erzeugt auch Metadaten zur Beschreibung von Stapel- und globalen Variablen. Mit diesen Metadaten kann die Laufzeit präzise Fehlerdiagnosen generieren: Funktionsnamen, Zeilen und Spalten im Quellcode. In Kombination können die Compilerüberprüfungen und Laufzeitbibliotheken viele Arten von Speichersicherheitsfehlern genau diagnostizieren, wenn sie zur Laufzeit aufgetreten sind.
Die Liste der Laufzeitbibliotheken zum Verknüpfen mit der AddressSanitizer-Laufzeit ab Visual Studio 17.7 Preview 3 folgt. Weitere Informationen zu den /MT
Optionen (statisch verknüpfen die Laufzeit) und /MD
(dynamisch verknüpfen sie den Redist zur Laufzeit) finden Sie unter /MD, /MT, /LD (Laufzeitbibliothek verwenden).
Hinweis
In der folgenden Tabelle {arch}
ist entweder i386
oder x86_64
.
Diese Bibliotheken verwenden Clang-Konventionen für Architekturnamen. MSVC-Konventionen sind normalerweise x86
und x64
nicht i386
und x86_64
, aber sie beziehen sich auf die gleichen Architekturen.
CRT-Option | AddressSanitizer-Laufzeitbibliothek (.lib) | Adresslaufzeit-Binärdatei (.dll) |
---|---|---|
/MT oder /MTd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_static_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MD oder /MDd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
Das folgende Diagramm zeigt, wie die Sprachlaufzeitbibliotheken für die /MT
Optionen , /MTd
, /MD
und /MDd
Compiler verknüpft sind:
Die Abbildung zeigt drei Szenarien zum Verknüpfen der Laufzeitbibliothek. Der erste ist /MT oder /MTd. My_exe.exe und my_dll.dll werden beide mit ihren eigenen Kopien der statisch verknüpften VCRuntime-, Universal CRT- und C++-Laufzeiten angezeigt. Die Szenarien zeigen /MD, in denen sowohl my_exe.exe als auch my_dll.dll vcruntime140.dll, ucrtbase.dll und msvcp140.dll teilen. Das letzte Szenario zeigt /MDd, in dem sowohl my_exe.exe als auch my_dll.dll die Debugversionen der Laufzeiten gemeinsam nutzen: vcruntime140d.dll, ucrtbased.dll und msvcp140d.dll
Das folgende Diagramm zeigt, wie die ASan-Bibliothek für verschiedene Compileroptionen verknüpft ist:
Die Abbildung zeigt vier Szenarien zum Verknüpfen der ASan-Laufzeitbibliothek. Die Szenarien gelten für /MT (statisch verknüpfen die Laufzeit), /MTd (statisch die Debuglaufzeit verknüpfen), /MD (dynamisch den Redist zur Laufzeit verknüpfen), /MDd (dynamisch den Debug-Redist zur Laufzeit verknüpfen). In allen Fällen my_exe.exe Verknüpfungen und die zugehörigen verknüpfungen my_dll.dll mit einer einzelnen Instanz von clang-rt.asan-dynamix-x86_64.dll.
Auch wenn die Statischverknüpfung erfolgt, muss die ASan-Laufzeit-DLL zur Laufzeit vorhanden sein – im Gegensatz zu anderen C-Runtime-Komponenten.
Frühere Versionen
Vor Visual Studio 17.7 Preview 3 wurden statisch verknüpfte (/MT
oder /MTd
) Builds keine DLL-Abhängigkeit verwendet. Stattdessen wurde die AddressSanitizer-Laufzeit statisch mit der EXE des Benutzers verknüpft. DLL-Projekte würden dann Exporte aus der EXE des Benutzers laden, um auf die ASan-Funktionalität zuzugreifen.
Dynamisch verknüpfte Projekte (/MD
oder /MDd
) verwendeten unterschiedliche Bibliotheken und DLLs, je nachdem, ob das Projekt für das Debuggen oder Release konfiguriert wurde. Weitere Informationen zu diesen Änderungen und ihren Motivationen finden Sie unter MSVC Address Sanitizer – Eine DLL für alle Laufzeitkonfigurationen.
In der folgenden Tabelle wird das vorherige Verhalten der AddressSanitizer-Laufzeitbibliotheksverknüpfung vor Visual Studio 17.7 Preview 3 beschrieben:
CRT-Option | DLL oder EXE | DEBUGGEN? | ASan-Bibliothek (.lib ) |
ASan-Laufzeit-Binärdatei (.dll ) |
---|---|---|---|---|
/MT |
EXE | No | clang_rt.asan-{arch} , clang_rt.asan_cxx-{arch} |
Keine |
/MT |
DLL | No | clang_rt.asan_dll_thunk-{arch} |
Keine |
/MD |
Entweder | No | clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MT |
EXE | Ja | clang_rt.asan_dbg-{arch} , clang_rt.asan_dbg_cxx-{arch} |
Keine |
/MT |
DLL | Ja | clang_rt.asan_dbg_dll_thunk-{arch} |
Keine |
/MD |
Sowohl als auch | Ja | clang_rt.asan_dbg_dynamic-{arch} , clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dbg_dynamic-{arch} |
Das folgende Diagramm zeigt, wie die ASan-Bibliothek für verschiedene Compileroptionen vor Visual Studio 2022 17.7 Preview 3 verknüpft wurde:
Die Abbildung zeigt vier Szenarien zum Verknüpfen der ASan-Laufzeitbibliothek. Die Szenarien gelten für /MT (statisch verknüpfen die Laufzeit), /MTd (statisch die Debuglaufzeit verknüpfen), /MD (dynamisch den Redist zur Laufzeit verknüpfen), /MDd (dynamisch den Debug-Redist zur Laufzeit verknüpfen). Für /MT verfügt my_exe.exe über eine statisch verknüpfte Kopie der ASan-Laufzeit. my_dll.dll Links zur ASan-Laufzeit in my_exe.exe. Bei /MTd ist das Diagramm identisch, mit der Ausnahme, dass es die statisch verknüpfte ASan-Laufzeit des Debugs verwendet. Bei /MD verknüpfen sowohl my_exe.exe als auch my_dll.dll mit der dynamisch verknüpften ASan-Laufzeit mit dem Namen clang_rt.asan_dynamic-x86_64.dll. Bei /MDd ist das Diagramm identisch, mit Ausnahme von my_exe.exe und my_dll.dll Verknüpfung mit der Debug-ASan-Laufzeit mit dem Namen clang_rt.asan_dbg_dynamic-x86_64.dll.
Funktionsinterception
Der AddressSanitizer erreicht funktionsübergreifende Abfangen durch viele Hotpatching-Techniken. Diese Techniken werden am besten im Quellcode selbst dokumentiert.
Die Laufzeitbibliotheken abfangen viele gängige Speicherverwaltungs- und Speichermanipulationsfunktionen ab. Eine Liste finden Sie unter AddressSanitizer-Liste der abgefangenen Funktionen. Die Zuordnungs-Interceptors verwalten Metadaten und Schattenbytes im Zusammenhang mit jedem Zuordnungsaufruf. Jedes Mal, wenn eine CRT-Funktion wie malloc
oder delete
aufgerufen wird, legen die Interceptors bestimmte Werte im AddressSanitizer-Schattenspeicherbereich fest, um anzugeben, ob diese Heap-Speicherorte derzeit zugänglich sind und welche Grenzen die Zuordnung sind. Mit diesen Schattenbytes können die vom Compiler generierten Überprüfungen der Schattenbytes bestimmen, ob eine Last oder ein Speicher gültig ist.
Das Abfangen ist nicht garantiert erfolgreich. Wenn eine Funktionsprologe zu kurz ist, um geschrieben jmp
zu werden, kann das Abfangen fehlschlagen. Wenn ein Abhörfehler auftritt, löst das Programm ein debugbreak
und hält an. Wenn Sie einen Debugger anfügen, wird die Ursache für das Abfangen klar. Wenn Sie dieses Problem haben, melden Sie einen Fehler.
Hinweis
Benutzer können optional versuchen, eine fehlgeschlagene Abfangen fortzusetzen, indem Sie die Umgebungsvariable ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE
auf einen beliebigen Wert festlegen. Wenn sie über einen Abfangenfehler hinaus fortgesetzt werden, kann dies zu verpassten Fehlerberichten für diese Funktion führen.
Benutzerdefinierte Zuweisungen und die AddressSanitizer-Laufzeit
Die AddressSanitizer-Laufzeit stellt Interceptors für allgemeine Allocator-Schnittstellen, malloc
free
/, ,/HeapFree
/HeapAlloc
delete
new
(viaRtlAllocateHeap
/RtlFreeHeap
) bereit. Viele Programme verwenden benutzerdefinierte Allokatoren aus einem Grund oder einem anderen, ein Beispiel wäre ein beliebiges Programm, das oder dlmalloc
eine Lösung mit der std::allocator
Schnittstelle und VirtualAlloc()
. Der Compiler kann einem benutzerdefinierten Zuweisungsvermerk nicht automatisch Schattenspeicherverwaltungsaufrufe hinzufügen. Es liegt in der Verantwortung des Benutzers, die bereitgestellte manuelle Vergiftungsschnittstelle zu verwenden. Diese API ermöglicht es diesen Allocators, ordnungsgemäß mit den vorhandenen AddressSanitizer-Laufzeit- und Schattenbytekonventionen zu funktionieren.
Manuelle AddressSanitizer-Vergiftungsschnittstelle
Die Benutzeroberfläche für die Optimierung ist einfach, sie legt jedoch Ausrichtungseinschränkungen für den Benutzer fest. Benutzer können diese Prototypen importieren, indem sie importiert sanitizer/asan_interface.h
werden. Hier sind die Prototypen der Schnittstellenfunktion:
void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
Aus Gründen der Einfachheit stellt die Headerdatei der AddressSanitizer-Schnittstelle Wrappermakros bereit. Diese Makros überprüfen, ob die AddressSanitizer-Funktion während der Kompilierung aktiviert ist. Sie ermöglichen es Ihrem Quellcode, die Vergiftungsfunktionsaufrufe auszulassen, wenn sie nicht benötigt werden. Diese Makros sollten bevorzugt werden, um die oben genannten Funktionen direkt aufzurufen:
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Ausrichtungsanforderungen für AddressSanitizer-Vergiftungen
Jede manuelle Vergiftung von Schattenbytes muss die Ausrichtungsanforderungen berücksichtigen. Der Benutzer muss bei Bedarf Abstand hinzufügen, damit die Schattenbytes auf einer Bytegrenze im Schattenspeicher enden. Jedes Bit im AddressSanitizer-Schattenspeicher codiert den Zustand eines einzelnen Byte im Speicher der Anwendung. Diese Codierung bedeutet, dass die Gesamtgröße jeder Zuordnung einschließlich des Abstands an einer Grenze von 8 Byte ausgerichtet werden muss. Wenn die Ausrichtungsanforderung nicht erfüllt ist, kann dies zu einer falschen Fehlerberichterstattung führen. Die falsche Berichterstattung kann als fehlende Berichte (falsch negativ) oder Berichte zu Nichtfehlern (falsch positive Ergebnisse) manifestieren.
Eine Abbildung der Ausrichtungsanforderung und potenziellen Probleme finden Sie in den bereitgestellten ASan-Ausrichtungsbeispielen. Eines ist ein kleines Programm, um zu zeigen, was mit manueller Schattenspeichervergiftung schief gehen kann. Die zweite ist ein Beispiel für die Implementierung manueller Vergiftungen mit der std::allocator
Schnittstelle.
Laufzeitoptionen
Microsoft C/C++ (MSVC) verwendet eine Laufzeit basierend auf der Clang AddressSanitizer-Laufzeit aus dem llvm-Projekt-Repository. Aus diesem Fall werden die meisten Laufzeitoptionen zwischen den beiden Versionen gemeinsam genutzt. Hier finden Sie eine vollständige Liste der öffentlichen Clang-Laufzeitoptionen. Wir dokumentieren einige Unterschiede in den folgenden Abschnitten. Wenn Sie Optionen entdecken, die nicht wie erwartet funktionieren, melden Sie einen Fehler.
Nicht unterstützte AddressSanitizer-Optionen
- detect_container_overflow
- unmap_shadow_on_exit
Hinweis
Die AddressSanitizer-Laufzeitoption halt_on_error
funktioniert nicht wie erwartet. Sowohl in den Clang- als auch in den MSVC-Laufzeitbibliotheken gelten viele Fehlertypen als nicht kontinuierbar, einschließlich der meisten Speicherbeschädigungsfehler.
Weitere Informationen finden Sie im Abschnitt "Unterschiede mit Clang 12.0 ".
MSVC-spezifische AddressSanitizer-Laufzeitoptionen
windows_hook_legacy_allocators
Boolescher Wert, der zumfalse
Deaktivieren der Abfangen von undLocalAlloc
AllokatorenGlobalAlloc
festgelegt ist.Hinweis
Die Option
windows_hook_legacy_allocators
war in der öffentlichen Llvm-Projektlaufzeit nicht verfügbar, als dieser Artikel geschrieben wurde. Die Option kann schließlich wieder zum öffentlichen Projekt beigetragen werden; Dies hängt jedoch von der Codeüberprüfung und der Akzeptanz der Community ab.Die Option
windows_hook_rtl_allocators
, zuvor ein Opt-In-Feature, während AddressSanitizer experimentell war, ist jetzt standardmäßig aktiviert. In Versionen vor Visual Studio 2022, Version 17.4.6, lautetfalse
der Standardwert . In Visual Studio 2022, Version 17.4.6 und höher, ist die Optionwindows_hook_rtl_allocators
standardmäßig auftrue
.iat_overwrite
Zeichenfolge, standardmäßig auf"error"
festgelegt. Andere mögliche Werte sind"protect"
und"ignore"
. Einige Module überschreiben möglicherweise dieimport address table
anderen Module, um Implementierungen bestimmter Funktionen anzupassen. Treiber stellen z. B. häufig benutzerdefinierte Implementierungen für bestimmte Hardware bereit. Dieiat_overwrite
Option verwaltet den Schutz der AddressSanitizer-Laufzeit vor Überschreibungen für bestimmtememoryapi.h
Funktionen. Die Laufzeit verfolgt derzeit dieVirtualAlloc
SchutzfunktionenVirtualProtect
, undVirtualQuery
die Funktionen. Diese Option ist in Visual Studio 2022, Version 17.5 Preview 1 und höher, verfügbar. Die folgendeniat_overwrite
Werte steuern, wie die Laufzeit reagiert, wenn geschützte Funktionen überschrieben werden:- Bei Festlegung auf
"error"
(Standardeinstellung) meldet die Laufzeit immer dann einen Fehler, wenn ein Überschreiben erkannt wird. - Bei Festlegung auf
"protect"
, versucht die Laufzeit, die Verwendung der überschriebenen Definition zu vermeiden und fortzufahren. Effektiv wird die ursprünglichememoryapi
Definition der Funktion innerhalb der Laufzeit verwendet, um unendliche Rekursion zu vermeiden. Andere Module im Prozess verwenden weiterhin die überschriebene Definition. - Bei Festlegung auf
"ignore"
, versucht die Laufzeit nicht, überschriebene Funktionen zu korrigieren und mit der Ausführung fortzufahren.
- Bei Festlegung auf
windows_fast_fail_on_error
Boolescher Wert (standardmäßig false) wird so festgelegt, dasstrue
der Prozess nach dem Drucken des Fehlerberichts mit einem __fastfail(71) beendet werden kann.
Hinweis
Wenn abort_on_error Wert auf "true" festgelegt ist, wird das Programm unter Windows mit einem Exit(3) beendet. Um das aktuelle Verhalten nicht zu ändern, haben wir uns entschieden, stattdessen diese neue Option einzuführen. Wenn sowohl abort_on_error als auch windows_fast_fail_on_error wahr sind, wird das Programm mit dem __fastfail beendet.
AddressSanitizer-Liste der abgefangenen Funktionen (Windows)
Die AddressSanitizer-Laufzeit hotpatcht viele Funktionen, um Speichersicherheitsprüfungen zur Laufzeit zu ermöglichen. Hier ist eine nicht erschöpfende Liste der Funktionen, die die AddressSanitizer-Laufzeit überwacht.
Standardabschnitte
__C_specific_handler
(nur x64)_aligned_free
_aligned_malloc
_aligned_msize
_aligned_realloc
_calloc_base
_calloc_crt
_calloc_dbg
(nur Debuglaufzeit)_except_handler3
(nur x86)_except_handler4
(nur x86) (nicht dokumentiert)_expand
_expand_base
(nicht dokumentiert)_expand_dbg
(nur Debuglaufzeit)_free_base
(nicht dokumentiert)_free_dbg
(nur Debuglaufzeit)_malloc_base
(nicht dokumentiert)_malloc_crt
(nicht dokumentiert)_malloc_dbg
(nur Debuglaufzeit)_msize
_msize_base
(nicht dokumentiert)_msize_dbg
(nur Debuglaufzeit)_realloc_base
(nicht dokumentiert)_realloc_crt
(nicht dokumentiert)_realloc_dbg
(nur Debuglaufzeit)_recalloc
_recalloc_base
(nicht dokumentiert)_recalloc_crt
(nicht dokumentiert)_recalloc_dbg
(nur Debuglaufzeit)_strdup
atoi
atol
calloc
CreateThread
free
frexp
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
RaiseException
realloc
RtlAllocateHeap
RtlCreateHeap
RtlDestroyHeap
RtlFreeHeap
RtlRaiseException
RtlReAllocateHeap
(nicht dokumentiert)RtlSizeHeap
(nicht dokumentiert)SetUnhandledExceptionFilter
strcat
strchr
strcmp
strcpy
strcspn
strdup
strlen
strncat
strncmp
strncpy
strnlen
strpbrk
strspn
strstr
strtok
strtol
wcslen
wcsnlen
Optionale Interceptors
Die hier aufgeführten Interceptors werden nur installiert, wenn eine AddressSanitizer-Laufzeitoption aktiviert ist. Legen Sie diese Einstellung windows_hook_legacy_allocators
fest, false
um die Legacy-Allocator-Abfangen zu deaktivieren.
set ASAN_OPTIONS=windows_hook_legacy_allocators=false
GlobalAlloc
GlobalFree
GlobalHandle
GlobalLock
GlobalReAlloc
GlobalSize
GlobalUnlock
LocalAlloc
LocalFree
LocalHandle
LocalLock
LocalReAlloc
LocalSize
LocalUnlock
Siehe auch
AddressSanitizer -Übersicht
Beheben bekannter Probleme mit demSanitizer
AddressSanitizer Build- und Sprachreferenz
AddressSanitizer-Schattenbytes
AddressSanitizer-Cloud oder verteilte Tests
AddressSanitizer Debugger-Integration
Beispiele für AddressSanitizer-Fehler