AddressSanitizer - AddressSanitizer
AddressSanitizer (nebo ASan ) je open source programovací nástroj, který detekuje chyby v poškození paměti , například přetečení vyrovnávací paměti nebo přístup k visícímu ukazateli (použití po uvolnění). AddressSanitizer je založen na nástrojích kompilátoru a přímo mapované stínové paměti . AddressSanitizer je aktuálně implementován v jazycích Clang (od verze 3.1), GCC (od verze 4.8), Xcode (od verze 7.0) a MSVC (široce dostupné od verze 16.9). V průměru přístrojové vybavení prodlužuje dobu zpracování o zhruba 73% a využití paměti o 240%.
Uživatelé
Vývojáři Chromium a Firefox jsou aktivními uživateli AddressSanitizer; nástroj našel v těchto webových prohlížečích stovky chyb. Ve FFmpeg a FreeType byla nalezena řada chyb . Linux kernel umožnil AddressSanitizer pro x86-64 architektuře jako Linux verze 4.0.
KernelAddressSanitizer
KernelAddressSanitizer ( Kasan ) zjistí dynamické chyby paměti v jádře Linux. Instrumentace jádra vyžaduje speciální funkci v kompilátoru poskytujícím možnost -fsanitize=kernel-addresspříkazového řádku, protože jádra nepoužívají stejný adresní prostor jako běžné programy.
Příklady
Heap-use-after-free
// To compile: g++ -O -g -fsanitize=address heap-use-after-free.cc
int main(int argc, char **argv) {
int *array = new int[100];
delete [] array;
return array[argc]; // BOOM
}
$ ./a.out ==5587==ERROR: AddressSanitizer: heap-use-after-free on address 0x61400000fe44 at pc 0x47b55f bp 0x7ffc36b28200 sp 0x7ffc36b281f8 READ of size 4 at 0x61400000fe44 thread T0 #0 0x47b55e in main /home/test/example_UseAfterFree.cc:5 #1 0x7f15cfe71b14 in __libc_start_main (/lib64/libc.so.6+0x21b14) #2 0x47b44c in _start (/root/a.out+0x47b44c) 0x61400000fe44 is located 4 bytes inside of 400-byte region [0x61400000fe40,0x61400000ffd0) freed by thread T0 here: #0 0x465da9 in operator delete[](void*) (/root/a.out+0x465da9) #1 0x47b529 in main /home/test/example_UseAfterFree.cc:4 previously allocated by thread T0 here: #0 0x465aa9 in operator new[](unsigned long) (/root/a.out+0x465aa9) #1 0x47b51e in main /home/test/example_UseAfterFree.cc:3 SUMMARY: AddressSanitizer: heap-use-after-free /home/test/example_UseAfterFree.cc:5 main Shadow bytes around the buggy address: 0x0c287fff9f70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c287fff9f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c287fff9f90: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c287fff9fa0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c287fff9fb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x0c287fff9fc0: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd 0x0c287fff9fd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c287fff9fe0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c287fff9ff0: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa 0x0c287fffa000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c287fffa010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==5587==ABORTING
Přetečení hromádky
// RUN: clang++ -O -g -fsanitize=address %t && ./a.out
int main(int argc, char **argv) {
int *array = new int[100];
array[0] = 0;
int res = array[argc + 100]; // BOOM
delete [] array;
return res;
}
==25372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x61400000ffd4 at pc 0x0000004ddb59 bp 0x7fffea6005a0 sp 0x7fffea600598 READ of size 4 at 0x61400000ffd4 thread T0 #0 0x46bfee in main /tmp/main.cpp:4:13 0x61400000ffd4 is located 4 bytes to the right of 400-byte region [0x61400000fe40,0x61400000ffd0) allocated by thread T0 here: #0 0x4536e1 in operator delete[](void*) #1 0x46bfb9 in main /tmp/main.cpp:2:16
Přetečení zásobníku
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int main(int argc, char **argv) {
int stack_array[100];
stack_array[1] = 0;
return stack_array[argc + 100]; // BOOM
}
==7405==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff64740634 at pc 0x46c103 bp 0x7fff64740470 sp 0x7fff64740468 READ of size 4 at 0x7fff64740634 thread T0 #0 0x46c102 in main /tmp/example_StackOutOfBounds.cc:5 Address 0x7fff64740634 is located in stack of thread T0 at offset 436 in frame #0 0x46bfaf in main /tmp/example_StackOutOfBounds.cc:2 This frame has 1 object(s): [32, 432) 'stack_array' <== Memory access at offset 436 overflows this variable
Globální přetečení vyrovnávací paměti
// RUN: clang -O -g -fsanitize=address %t && ./a.out
int global_array[100] = {-1};
int main(int argc, char **argv) {
return global_array[argc + 100]; // BOOM
}
==7455==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000689b54 at pc 0x46bfd8 bp 0x7fff515e5ba0 sp 0x7fff515e5b98 READ of size 4 at 0x000000689b54 thread T0 #0 0x46bfd7 in main /tmp/example_GlobalOutOfBounds.cc:4 0x000000689b54 is located 4 bytes to the right of global variable 'global_array' from 'example_GlobalOutOfBounds.cc' (0x6899c0) of size 400
Omezení
AddressSanitizer nezjistí žádná neinicializovaná čtení z paměti (ale toto zjistí program MemorySanitizer ) a detekuje pouze některé chyby použití po návratu. Není také schopen detekovat všechny chyby poškození libovolné paměti ani všechny chyby libovolného zápisu v důsledku přetečení/přetečení celého čísla (když se pro výpočet posunů adres paměti používá celé číslo s nedefinovaným chováním). Sousední vyrovnávací paměti ve strukturách a třídách nejsou chráněny před přetečením, částečně proto, aby se zabránilo narušení zpětné kompatibility.
Viz také
- Intel MPX
- Ověřovač aplikací (AppVerif.exe) v sadě Microsoft Windows SDK
Reference
externí odkazy
- Skupina Google AddressSanitizer (žádný seznam adresátů)
- Stránka projektu AddressSanitizer
- Dokumentace AddressSanitizer (Clang)