Bajty w tle addressSanitizer
Krótko podsumujemy koncepcję bajtów w tle i sposobu ich użycia przez implementację środowiska uruchomieniowego programu /fsanitize=address
. Aby uzyskać więcej informacji, zapoznaj się z początkową dokumentacją algorytmu AddressSanitizer - Serebryany i in.
Podstawowa koncepcja
Co 8 bajtów w wirtualnej przestrzeni adresowej aplikacji można opisać przy użyciu jednego bajtu w tle.
Jeden bajt w tle opisuje, ile bajtów jest obecnie dostępnych w następujący sposób:
- 0 oznacza wszystkie 8 bajtów
- 1–7 oznacza od jednego do siedmiu bajtów
- Liczby ujemne kodują kontekst środowiska uruchomieniowego do użycia na potrzeby diagnostyki raportowania.
Legenda bajtów cienia
Rozważmy tę legendę bajtów w tle, w której zdefiniowano wszystkie liczby ujemne:
Mapowanie — opisywanie przestrzeni adresowej
Co 8 bajtów w wirtualnej przestrzeni adresowej aplikacji, która jest wyrównana "0-mod-8", można zamapować na bajt w tle, który opisuje to miejsce w wirtualnej przestrzeni adresowej. To mapowanie można wykonać za pomocą prostego przesunięcia i dodania.
W systemie x86:
char shadow_byte_value = *((Your_Address >> 3) + 0x30000000)
Na x64:
char shadow_byte_value = *((Your_Address >> 3) + _asan_runtime_assigned_offset)
Generowanie kodu — testy
Zastanów się, w jaki sposób określone bajty w tle mogą być zapisywane przez kod wygenerowany przez kompilator, dane statyczne lub środowisko uruchomieniowe. Ten pseudo-kod pokazuje, jak można wygenerować kontrolę poprzedzającą wszelkie obciążenia lub magazyn:
ShadowAddr = (Addr >> 3) + Offset;
if (*ShadowAddr != 0) {
ReportAndCrash(Addr);
}
Instrumentacja w przypadku instrumentacji odwołania do pamięci, która jest mniejsza niż 8 bajtów, instrumentacja jest nieco bardziej złożona. Jeśli wartość cienia jest dodatnia (co oznacza, że można uzyskać dostęp tylko do pierwszych k bajtów w 8-bajtowym słowie), musimy porównać ostatnie 3 bity adresu z k.
ShadowAddr = (Addr >> 3) + Offset;
k = *ShadowAddr;
if (k != 0 && ((Addr & 7) + AccessSize > k)) {
ReportAndCrash(Addr);
}
Środowisko uruchomieniowe i kod wygenerowany przez kompilator zapisują bajty w tle. Te bajty w tle zezwalają na dostęp lub odwoływanie dostępu, gdy zakresy kończą się lub są zwalniane. Powyższe kontrole odczytują bajty w tle, które opisują 8-bajtowe "gniazda" w przestrzeni adresowej aplikacji w określonym czasie wykonywania programu. Oprócz tych jawnie wygenerowanych kontroli środowisko uruchomieniowe sprawdza również bajty w tle po przechwyceniu (lub "hakach") wielu funkcji w CRT.
Aby uzyskać więcej informacji, zobacz listę przechwyconych funkcji.
Ustawianie bajtów w tle
Zarówno kod generowany przez kompilator, jak i środowisko uruchomieniowe AddressSanitizer może zapisywać bajty w tle. Na przykład kompilator może ustawić bajty w tle, aby zezwolić na stały dostęp do stosu ustawień lokalnych zdefiniowanych w zakresie wewnętrznym. Środowisko uruchomieniowe może otaczać zmienne globalne w sekcji danych z bajtami w tle.
Zobacz też
AddressSanitizer — omówienie
Rozwiązywanie znanych problemów z programemSanitizer
Dokumentacja języka i kompilacji narzędzia AddressSanitizer
AddressSanitizer runtime reference (Dokumentacja środowiska uruchomieniowego AddressSanitizer)
AddressSanitizer — chmura lub testowanie rozproszone
Integracja debugera AddressSanitizer
Przykłady błędów addressSanitizer