Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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=addressprogramu 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 Run-Time).
Note
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 /MTopcjami kompilatora , , /MTd, /MDi /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_dynamic-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 AddressSanitizer — 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 | DEBUG? | Biblioteka ASan (.lib) |
Dane binarne środowiska uruchomieniowego ASan (.dll) |
|---|---|---|---|---|
/MT |
EXE | No |
clang_rt.asan-{arch}, clang_rt.asan_cxx-{arch} |
None |
/MT |
DLL | No | clang_rt.asan_dll_thunk-{arch} |
None |
/MD |
Either | No |
clang_rt.asan_dynamic-{arch}, clang_rt.asan_dynamic_runtime_thunk-{arch} |
clang_rt.asan_dynamic-{arch} |
/MT |
EXE | Yes |
clang_rt.asan_dbg-{arch}, clang_rt.asan_dbg_cxx-{arch} |
None |
/MT |
DLL | Yes | clang_rt.asan_dbg_dll_thunk-{arch} |
None |
/MD |
Either | Yes |
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ę.
Note
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,HeapAlloc/HeapFree(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.hplik . 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)
Note
Jeśli ręcznie zatruwasz pamięć, musisz ją usunąć przed ponownym użyciem. Jest to szczególnie ważne w przypadku adresów stosu, takich jak zmienna lokalna, która jest często używana podczas wykonywania programu. Ryzyko wprowadzenia use-after-poison fałszywych wyników dodatnich w ręcznie zatrutych adresach stosu, jeśli nie usuniesz ich przed usunięciem ramki stosu.
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 środowiska uruchomieniowego
MSVC AddressSanitizer to regularnie synchronizowane rozwidlenie środowiska uruchomieniowego Clang AddressSanitizer. W związku z tym MSVC niejawnie dziedziczy wiele opcji środowiska uruchomieniowego ASan języka Clang. Pełną listę opcji, które aktywnie utrzymujemy i test można znaleźć tutaj. Jeśli odkryjesz opcje, które nie działają zgodnie z oczekiwaniami, zgłoś usterkę.
Konfigurowanie opcji środowiska uruchomieniowego
Opcje środowiska uruchomieniowego ASan są ustawiane na jeden z dwóch sposobów:
- Zmienna środowiskowa
ASAN_OPTIONS -
__asan_default_optionsFunkcja użytkownika
Jeśli zmienna środowiskowa i funkcja użytkownika określają opcje powodujące konflikt, opcje w zmiennej środowiskowej ASAN_OPTIONS mają pierwszeństwo.
Wiele opcji jest określonych przez oddzielenie ich dwukropkiem (:).
Poniższy przykład ustawia wartość alloc_dealloc_mismatch na jedną i symbolize zero:
set ASAN_OPTIONS=alloc_dealloc_mismatch=1:symbolize=0
Możesz też dodać następującą funkcję do kodu:
extern "C" const char* __asan_default_options()
{
return "alloc_dealloc_mismatch=1:symbolize=0";
}
Nieobsługiwane opcje AddressSanitizer
detect_container_overflowunmap_shadow_on_exit
Note
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
continue_on_errorWartość logiczna ustawiona nafalsewartość domyślną. Gdy jest ustawiona wartośćtrue, umożliwia programowi kontynuowanie wykonywania po zgłoszeniu naruszenia pamięci, co umożliwia zbieranie wielu raportów o błędach.iat_overwriteCią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 tableinne 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_overwritezarządza ochroną środowiska uruchomieniowego AddressSanitizer przed zastąpieniem określonychmemoryapi.hfunkcji. Środowisko uruchomieniowe śledzi obecnieVirtualAllocfunkcje ,VirtualProtectiVirtualQueryna 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_overwritewartoś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 oryginalnamemoryapidefinicja 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_errorWartość logiczna (falsedomyślnie) jest ustawiona na wartość , abytrueumożliwić zakończenie procesu z wartością__fastfail(71)po wydrukowaniu raportu o błędach.Note
Gdy
abort_on_errorwartość jest ustawiona natrue, w systemie Windows program kończy działanie za pomocą .exit(3)Aby nie zmienić bieżącego zachowania, postanowiliśmy wprowadzić tę nową opcję. Jeśli zarównoabort_on_error, jak iwindows_fast_fail_on_errortrue, program zakończy działanie za pomocą polecenia__fastfail.windows_hook_legacy_allocatorsWartość logiczna, ustawiona na wartość , abyfalsewyłączyć przechwytywanieGlobalAllocobiektów iLocalAllocalokatorów.Note
Opcja
windows_hook_legacy_allocatorsnie 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_allocatorsjest domyślnie ustawiona natrue.
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) _strdupatoiatolcallocCreateThreadfreefrexplongjmpmallocmemchrmemcmpmemcpymemmovememsetRaiseExceptionreallocRtlAllocateHeapRtlCreateHeapRtlDestroyHeapRtlFreeHeapRtlRaiseException-
RtlReAllocateHeap(nieudokumentowane) -
RtlSizeHeap(nieudokumentowane) SetUnhandledExceptionFilterstrcatstrchrstrcmpstrcpystrcspnstrdupstrlenstrncatstrncmpstrncpystrnlenstrpbrkstrspnstrstrstrtokstrtolwcslenwcsnlen
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
GlobalAllocGlobalFreeGlobalHandleGlobalLockGlobalReAllocGlobalSizeGlobalUnlockLocalAllocLocalFreeLocalHandleLocalLockLocalReAllocLocalSizeLocalUnlock
Zobacz także
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