AddressSanitizer runtime
Biblioteka środowiska uruchomieniowego AddressSanitizer przechwytuje typowe funkcje alokacji pamięci i operacje umożliwiające inspekcję dostępu do pamięci. Istnieje kilka różnych bibliotek środowiska uruchomieniowego, które obsługują różne typy plików wykonywalnych, które mogą być generowane przez kompilator. Kompilator i konsolidator automatycznie łączą odpowiednie biblioteki środowiska uruchomieniowego, o ile opcja zostanie przekazana /fsanitize=address
w czasie kompilacji. Domyślne zachowanie można zastąpić za pomocą /NODEFAULTLIB
opcji w czasie połączenia. Aby uzyskać więcej informacji, zobacz sekcję dotyczącą łączenia w języku AddressSanitizer, kompilacji i debugowaniu.
Podczas kompilowania za pomocą cl /fsanitize=address
programu kompilator generuje instrukcje dotyczące zarządzania bajtami w tle i sprawdzania ich. Program używa tej instrumentacji do sprawdzania dostępu do pamięci na stosie, w stercie lub w zakresie globalnym. Kompilator tworzy również metadane opisujące stos i zmienne globalne. Te metadane umożliwiają środowisku uruchomieniowemu generowanie dokładnej diagnostyki błędów: nazwy funkcji, wiersze i kolumny w kodzie źródłowym. W połączeniu kompilator sprawdza i biblioteki środowiska uruchomieniowego można dokładnie zdiagnozować wiele typów usterek bezpieczeństwa pamięci, jeśli wystąpią w czasie wykonywania.
Poniżej znajduje się lista bibliotek środowiska uruchomieniowego do łączenia ze środowiskiem uruchomieniowym AddressSanitizer w programie Visual Studio 17.7 (wersja zapoznawcza 3). Aby uzyskać więcej informacji na temat /MT
opcji (statycznie łączyć środowisko uruchomieniowe) i /MD
(dynamicznie łączyć redist w czasie wykonywania), zobacz /MD, /MT, /LD (Użyj biblioteki czasu wykonywania).
Uwaga
W poniższej tabeli {arch}
znajduje się wartość i386
lub x86_64
.
Te biblioteki używają konwencji języka Clang dla nazw architektury. Konwencje MSVC są zwykle x86
, a x64
nie i386
i x86_64
, ale odnoszą się do tych samych architektur.
Opcja CRT | Biblioteka środowiska uruchomieniowego AddressSanitizer (.lib) | Plik binarny środowiska uruchomieniowego adresu (.dll) |
---|---|---|
/MT lub /MTd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_static_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MD lub /MDd |
clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
Na poniższym diagramie przedstawiono sposób, w jaki biblioteki środowiska uruchomieniowego języka są połączone z /MT
opcjami kompilatora , , /MTd
, /MD
i /MDd
:
Obraz przedstawia trzy scenariusze łączenia biblioteki środowiska uruchomieniowego. Pierwszy to /MT lub /MTd. My_exe.exe i my_dll.dll są wyświetlane z własnymi kopiami statycznie połączonych środowisk VCRuntime, Universal CRT i C++. Scenariusze pokazują /MD, w których zarówno my_exe.exe, jak i my_dll.dll współużytkuje vcruntime140.dll, ucrtbase.dll i msvcp140.dll. W ostatnim scenariuszu pokazano /MDd, w którym zarówno my_exe.exe, jak i my_dll.dll współużytkować wersje debugowania środowisk uruchomieniowych: vcruntime140d.dll, ucrtbased.dll i msvcp140d.dll
Na poniższym diagramie przedstawiono sposób, w jaki biblioteka ASan jest połączona z różnymi opcjami kompilatora:
Obraz przedstawia cztery scenariusze łączenia biblioteki środowiska uruchomieniowego ASan. Scenariusze dotyczą /MT (statycznie połączyć środowisko uruchomieniowe), /MTd (statycznie połączyć środowisko uruchomieniowe debugowania), /MD (dynamicznie połączyć redystrybucj w czasie wykonywania), /MDd (dynamicznie połączyć redystrybut debugowania w czasie wykonywania). We wszystkich przypadkach my_exe.exe linki i jego skojarzenia my_dll.dll link do pojedynczego wystąpienia clang-rt.asan-dynamix-x86_64.dll.
Nawet w przypadku statycznego łączenia biblioteka DLL środowiska uruchomieniowego ASan musi być obecna w czasie wykonywania — w przeciwieństwie do innych składników środowiska uruchomieniowego języka C.
Poprzednie wersje
Przed programem Visual Studio 17.7 (wersja zapoznawcza 3) kompilacje statycznie połączone (/MT
lub /MTd
) nie używały zależności biblioteki DLL. Zamiast tego środowisko uruchomieniowe AddressSanitizer zostało statycznie połączone z plikiem EXE użytkownika. Następnie projekty DLL ładują eksporty z pliku EXE użytkownika w celu uzyskania dostępu do funkcji ASan.
Dynamicznie połączone projekty (/MD
lub /MDd
) używały różnych bibliotek i bibliotek DLL w zależności od tego, czy projekt został skonfigurowany do debugowania, czy wydania. Aby uzyskać więcej informacji na temat tych zmian i ich motywacji, zobacz MSVC Address Sanitizer — jedna biblioteka DLL dla wszystkich konfiguracji środowiska uruchomieniowego.
W poniższej tabeli opisano poprzednie zachowanie linku biblioteki środowiska uruchomieniowego AddressSanitizer przed programem Visual Studio 17.7 (wersja zapoznawcza 3):
Opcja CRT | BIBLIOTEKA DLL lub EXE | DEBUGOWAĆ? | Biblioteka ASan (.lib ) |
Dane binarne środowiska uruchomieniowego ASan (.dll ) |
---|---|---|---|---|
/MT |
EXE | Nie. | clang_rt.asan-{arch} , clang_rt.asan_cxx-{arch} |
Brak |
/MT |
DLL | Nie. | clang_rt.asan_dll_thunk-{arch} |
Brak |
/MD |
Lub | Nie. | clang_rt.asan_dynamic-{arch} , clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MT |
EXE | Tak | clang_rt.asan_dbg-{arch} , clang_rt.asan_dbg_cxx-{arch} |
Brak |
/MT |
DLL | Tak | clang_rt.asan_dbg_dll_thunk-{arch} |
None |
/MD |
Dowolny | Tak | clang_rt.asan_dbg_dynamic-{arch} , clang_rt.asan_dbg_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dbg_dynamic-{arch} |
Na poniższym diagramie pokazano, jak biblioteka ASan była połączona z różnymi opcjami kompilatora przed programem Visual Studio 2022 17.7 (wersja zapoznawcza 3):
Obraz przedstawia cztery scenariusze łączenia biblioteki środowiska uruchomieniowego ASan. Scenariusze dotyczą /MT (statycznie połączyć środowisko uruchomieniowe), /MTd (statycznie połączyć środowisko uruchomieniowe debugowania), /MD (dynamicznie połączyć redystrybucj w czasie wykonywania), /MDd (dynamicznie połączyć redystrybut debugowania w czasie wykonywania). W przypadku /MT my_exe.exe ma statycznie połączoną kopię środowiska uruchomieniowego ASan. my_dll.dll linki do środowiska uruchomieniowego ASan w my_exe.exe. W przypadku /MTd diagram jest taki sam, z wyjątkiem tego, że używa statycznie połączonego środowiska uruchomieniowego ASan debugowania. W przypadku /MD zarówno my_exe.exe, jak i my_dll.dll łącze do dynamicznie połączonego środowiska uruchomieniowego ASan o nazwie clang_rt.asan_dynamic-x86_64.dll. W przypadku /MDd diagram jest taki sam, z wyjątkiem my_exe.exe i my_dll.dll link do środowiska uruchomieniowego debugowania ASan o nazwie clang_rt.asan_dbg_dynamic-x86_64.dll.
Przechwytywanie funkcji
Funkcja AddressSanitizer umożliwia przechwytywanie funkcji za pomocą wielu technik na gorąco. Te techniki są najlepiej udokumentowane w samym kodzie źródłowym.
Biblioteki środowiska uruchomieniowego przechwytują wiele typowych funkcji zarządzania pamięcią i manipulowania pamięcią. Aby zapoznać się z listą, zobacz AddressSanitizer list of intercepted functions (Lista przechwyconych funkcji). Przechwytniki alokacji zarządzają metadanymi i bajtami w tle powiązanymi z każdym wywołaniem alokacji. Za każdym razem, gdy funkcja CRT, taka jak malloc
lub delete
jest wywoływana, przechwytatory ustawiają określone wartości w regionie Pamięci w tle AddressSanitizer, aby wskazać, czy te lokalizacje sterty są obecnie dostępne i jakie są granice alokacji. Te bajty w tle umożliwiają kompilatorowi sprawdzanie bajtów w tle w celu określenia, czy obciążenie lub magazyn jest prawidłowe.
Przechwytywanie nie ma gwarancji powodzenia. Jeśli prolog funkcji jest za krótki do jmp
zapisania, przechwytywanie może zakończyć się niepowodzeniem. Jeśli wystąpi błąd przechwytywania, program zgłasza błąd debugbreak
i zatrzymuje. Jeśli dołączysz debuger, przyczyną problemu przechwytywania jest jasne. Jeśli masz ten problem, zgłoś usterkę.
Uwaga
Użytkownicy mogą opcjonalnie próbować kontynuować przecięcie nieudanego przechwycenia, ustawiając zmienną środowiskową ASAN_WIN_CONTINUE_ON_INTERCEPTION_FAILURE
na dowolną wartość. Kontynuowanie niepowodzenia przechwytywania może spowodować pominięcie raportów o błędach dla tej funkcji.
Niestandardowe alokatory i środowisko uruchomieniowe AddressSanitizer
Środowisko uruchomieniowe AddressSanitizer udostępnia przechwytniki dla typowych interfejsów alokatora, malloc
/free
, new
delete
/,/HeapFree
HeapAlloc
(za pośrednictwem metody ).RtlAllocateHeap
/RtlFreeHeap
Wiele programów korzysta z niestandardowych alokatorów z jednego lub innego powodu, przykładem może być dowolny program korzystający z interfejsu lub rozwiązania przy użyciu dlmalloc
interfejsu std::allocator
i VirtualAlloc()
. Kompilator nie może automatycznie dodawać wywołań zarządzania pamięcią w tle do niestandardowego alokatora. Użytkownik ponosi odpowiedzialność za korzystanie z dostarczonego interfejsu zatruwania ręcznego. Ten interfejs API umożliwia tym alokatorom prawidłowe działanie z istniejącym środowiskiem uruchomieniowym AddressSanitizer i konwencjami bajtów w tle.
Interfejs zatruwania narzędzia AddressSanitizer ręcznego
Interfejs do obsługi jest prosty, ale nakłada ograniczenia wyrównania na użytkownika. Użytkownicy mogą importować te prototypy, importując sanitizer/asan_interface.h
plik . Oto prototypy funkcji interfejsu:
void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
Dla wygody plik nagłówka interfejsu AddressSanitizer udostępnia makra otoki. Te makra sprawdzają, czy funkcja AddressSanitizer jest włączona podczas kompilacji. Umożliwiają one kodowi źródłowemu pominięcie wywołań funkcji zatrucia, gdy nie są potrzebne. Te makra powinny być preferowane w przypadku bezpośredniego wywoływania powyższych funkcji:
#define ASAN_POISON_MEMORY_REGION(addr, size)
#define ASAN_UNPOISON_MEMORY_REGION(addr, size)
Wymagania dotyczące wyrównania dla zatrucia narzędzia AddressSanitizer
Każde ręczne zatrucie bajtów w tle musi uwzględniać wymagania dotyczące wyrównania. W razie potrzeby użytkownik musi dodać dopełnienie, aby bajty w tle zakończyły się granicą bajtów w pamięci w tle. Każdy bit w pamięci w tle AddressSanitizer koduje stan pojedynczego bajtu w pamięci aplikacji. To kodowanie oznacza całkowity rozmiar każdej alokacji, w tym wszelkie wypełnienie, musi być wyrównany do granicy 8-bajtowej. Jeśli wymaganie wyrównania nie jest spełnione, może to prowadzić do nieprawidłowego raportowania błędów. Niepoprawne raportowanie może manifestować się jako brakujące raporty (fałszywie ujemne) lub raporty dotyczące błędów (fałszywie dodatnie).
Aby zapoznać się z ilustracją wymagań dotyczących wyrównania i potencjalnych problemów, zobacz podane przykłady wyrównania rozwiązania ASan. Jednym z nich jest mały program, który pokazuje, co może pójść nie tak z ręcznym zatruciem pamięci w tle. Druga to przykładowa implementacja ręcznego zatrucia za pomocą interfejsu std::allocator
.
Opcje czasu wykonywania
Program Microsoft C/C++ (MSVC) używa środowiska uruchomieniowego opartego na środowisku uruchomieniowym Clang AddressSanitizer z repozytorium llvm-project. W związku z tym większość opcji środowiska uruchomieniowego jest współdzielona między dwiema wersjami. Pełna lista publicznych opcji środowiska uruchomieniowego Clang jest dostępna tutaj. Dokumentujemy pewne różnice w poniższych sekcjach. Jeśli odkryjesz opcje, które nie działają zgodnie z oczekiwaniami, zgłoś usterkę.
Nieobsługiwane opcje AddressSanitizer
- detect_container_overflow
- unmap_shadow_on_exit
Uwaga
Opcja halt_on_error
środowiska uruchomieniowego AddressSanitizer nie działa w oczekiwany sposób. W bibliotekach środowiska uruchomieniowego Clang i MSVC wiele typów błędów jest uznawanych za nieobsługiwalne, w tym większość błędów uszkodzenia pamięci.
Aby uzyskać więcej informacji, zobacz sekcję Różnice w języku Clang 12.0 .
Opcje środowiska uruchomieniowego narzędzia AddressSanitizer specyficzne dla MSVC
windows_hook_legacy_allocators
Wartość logiczna, ustawiona na wartość , abyfalse
wyłączyć przechwytywanieGlobalAlloc
obiektów iLocalAlloc
alokatorów.Uwaga
Opcja
windows_hook_legacy_allocators
nie była dostępna w publicznym środowisku uruchomieniowym llvm-project podczas pisania tego artykułu. Opcja może zostać ostatecznie wpłatwana z powrotem do projektu publicznego; jednak zależy to od przeglądu kodu i akceptacji społeczności.Opcja
windows_hook_rtl_allocators
, wcześniej włączona funkcja , podczas gdy funkcja AddressSanitizer była eksperymentalna, jest teraz domyślnie włączona. W wersjach wcześniejszych niż program Visual Studio 2022 w wersji 17.4.6 domyślną wartością opcji jestfalse
. W programie Visual Studio 2022 w wersji 17.4.6 lub nowszej opcjawindows_hook_rtl_allocators
jest domyślnie ustawiona natrue
.iat_overwrite
Ciąg, domyślnie ustawiony na"error"
wartość . Inne możliwe wartości to"protect"
i"ignore"
. Niektóre moduły mogą zastąpićimport address table
inne moduły w celu dostosowania implementacji niektórych funkcji. Na przykład sterowniki często udostępniają niestandardowe implementacje dla określonego sprzętu. Opcjaiat_overwrite
zarządza ochroną środowiska uruchomieniowego AddressSanitizer przed zastąpieniem określonychmemoryapi.h
funkcji. Środowisko uruchomieniowe śledzi obecnieVirtualAlloc
funkcje ,VirtualProtect
iVirtualQuery
na potrzeby ochrony. Ta opcja jest dostępna w programie Visual Studio 2022 w wersji 17.5 (wersja zapoznawcza 1) i nowszych wersjach. Następująceiat_overwrite
wartości określają, jak środowisko uruchomieniowe reaguje, gdy funkcje chronione są zastępowane:- Jeśli jest ustawiona wartość
"error"
(wartość domyślna), środowisko uruchomieniowe zgłasza błąd za każdym razem, gdy zostanie wykryte zastąpienie. - Jeśli jest ustawiona wartość
"protect"
, środowisko uruchomieniowe próbuje uniknąć używania zastąpionej definicji i przechodzi dalej. W rzeczywistości oryginalnamemoryapi
definicja funkcji jest używana z wewnątrz środowiska uruchomieniowego, aby uniknąć nieskończonej rekursji. Inne moduły w procesie nadal używają nadpisanej definicji. - Jeśli jest ustawiona wartość
"ignore"
, środowisko uruchomieniowe nie próbuje poprawić żadnych zastąpionych funkcji i kontynuuje wykonywanie.
- Jeśli jest ustawiona wartość
windows_fast_fail_on_error
Wartość logiczna (wartość domyślna false) jest ustawiona na wartość , abytrue
umożliwić zakończenie procesu z __fastfail(71) po wydrukowaniu raportu o błędach.
Uwaga
Gdy abort_on_error wartość jest ustawiona na true, w systemie Windows program kończy działanie z exit(3). Aby nie zmienić bieżącego zachowania, postanowiliśmy wprowadzić tę nową opcję. Jeśli zarówno abort_on_error, jak i windows_fast_fail_on_error są prawdziwe, program zakończy działanie z __fastfail.
AddressSanitizer lista przechwyconych funkcji (Windows)
Środowisko uruchomieniowe AddressSanitizer sprawdza wiele funkcji w celu włączenia kontroli bezpieczeństwa pamięci w czasie wykonywania. Oto niewyczerpująca lista funkcji monitorujących środowisko uruchomieniowe AddressSanitizer.
Domyślne przechwytniki
__C_specific_handler
(tylko x64)_aligned_free
_aligned_malloc
_aligned_msize
_aligned_realloc
_calloc_base
_calloc_crt
_calloc_dbg
(tylko środowisko uruchomieniowe debugowania)_except_handler3
(tylko x86)_except_handler4
(tylko x86) (nieudokumentowane)_expand
_expand_base
(nieudokumentowane)_expand_dbg
(tylko środowisko uruchomieniowe debugowania)_free_base
(nieudokumentowane)_free_dbg
(tylko środowisko uruchomieniowe debugowania)_malloc_base
(nieudokumentowane)_malloc_crt
(nieudokumentowane)_malloc_dbg
(tylko środowisko uruchomieniowe debugowania)_msize
_msize_base
(nieudokumentowane)_msize_dbg
(tylko środowisko uruchomieniowe debugowania)_realloc_base
(nieudokumentowane)_realloc_crt
(nieudokumentowane)_realloc_dbg
(tylko środowisko uruchomieniowe debugowania)_recalloc
_recalloc_base
(nieudokumentowane)_recalloc_crt
(nieudokumentowane)_recalloc_dbg
(tylko środowisko uruchomieniowe debugowania)_strdup
atoi
atol
calloc
CreateThread
free
frexp
longjmp
malloc
memchr
memcmp
memcpy
memmove
memset
RaiseException
realloc
RtlAllocateHeap
RtlCreateHeap
RtlDestroyHeap
RtlFreeHeap
RtlRaiseException
RtlReAllocateHeap
(nieudokumentowane)RtlSizeHeap
(nieudokumentowane)SetUnhandledExceptionFilter
strcat
strchr
strcmp
strcpy
strcspn
strdup
strlen
strncat
strncmp
strncpy
strnlen
strpbrk
strspn
strstr
strtok
strtol
wcslen
wcsnlen
Opcjonalne przechwytniki
Przechwytniki wymienione w tym miejscu są instalowane tylko wtedy, gdy jest włączona opcja środowiska uruchomieniowego AddressSanitizer. Ustaw windows_hook_legacy_allocators
wartość na , aby false
wyłączyć przechwytywanie starszej wersji alokatora.
set ASAN_OPTIONS=windows_hook_legacy_allocators=false
GlobalAlloc
GlobalFree
GlobalHandle
GlobalLock
GlobalReAlloc
GlobalSize
GlobalUnlock
LocalAlloc
LocalFree
LocalHandle
LocalLock
LocalReAlloc
LocalSize
LocalUnlock
Zobacz też
AddressSanitizer — omówienie
Rozwiązywanie znanych problemów z programemSanitizer
Dokumentacja języka i kompilacji narzędzia AddressSanitizer
Bajty w tle addressSanitizer
AddressSanitizer — chmura lub testowanie rozproszone
Integracja debugera AddressSanitizer
Przykłady błędów addressSanitizer