AddressSanitizer

редактировать

AddressSanitizer (или ASan ) - это инструмент программирования с открытым исходным кодом от Google который обнаруживает повреждение памяти ошибки, такие как переполнение буфера или доступ к висячему указателю (использование после освобождения). AddressSanitizer основан на компиляторе инструментарии и непосредственно отображаемой теневой памяти. AddressSanitizer в настоящее время реализован в Clang (начиная с версии 3.1), GCC (начиная с версии 4.8) и Xcode (начиная с версии 7.0). В среднем инструментарий увеличивает время обработки примерно на 73% и использование памяти на 240%.

Содержание
  • 1 Пользователи
  • 2 KernelAddressSanitizer
  • 3 Примеры
    • 3.1 Heap-use-after-free
    • 3.2 Переполнение буфера кучи
    • 3.3 Переполнение буфера стека
    • 3.4 Глобальное переполнение буфера
  • 4 Ограничения
  • 5 См. Также
  • 6 Ссылки
  • 7 Внешние ссылки
Пользователи

Разработчики Chromium и Firefox являются активными пользователями AddressSanitizer; инструмент обнаружил сотни ошибок в этих веб-браузерах. В FFmpeg и FreeType обнаружен ряд ошибок. Ядро Linux включило AddressSanitizer для архитектуры x86-64 начиная с версии Linux 4.0.

KernelAddressSanitizer

KernelAddressSanitizer (KASAN ) обнаруживает ошибки динамической памяти в ядре Linux. Инструментарий ядра требует специальной функции в компиляторе, предоставляющей параметр командной строки -fsanitize = kernel-address, поскольку ядра не используют то же адресное пространство, что и обычные программы.

Примеры

Heap-use-after-free

1 // Для компиляции: g ++ -O -g -fsanitize = address heap-use-after-free.cc 2 int main (int argc, char ** argv) { 3 int * array = new int [100]; 4 удалить массив; 5 вернуть массив [argc]; // BOOM 6}
$./a.out == 5587 == ОШИБКА: AddressSanitizer: heap-use-after-free на адресе 0x61400000fe44 на компьютере 0x47b55f bp 0x7ffc36b28200 sp 0x7ffc36b281f8 ЧТЕНИЕ размера 4 на 0x61400000fe44 thread T0 # 0x47b55e в главном /home/test/example_UseAfterFree.cc:7 # 1 0x7f15cfe71b14 в __libc_start_main (/lib64/libc.so.6+0x21b14) # 2 0x47b44c в _start (/root/a.out+0x471400c, расположенном в 4000 байтах) внутри 400-байтовой области [0x61400000fe40,0x61400000ffd0), освобожденной потоком T0 здесь: # 0 0x465da9 в операторе delete (void *) (/root/a.out+0x465da9) # 1 0x47b529 в основном файле /home/test/example_UseAfterFree.cc : 6 ранее выделено потоком T0 здесь: # 0 0x465aa9 в операторе new (unsigned long) (/root/a.out+0x465aa9) # 1 0x47b51e в основном /home/test/example_UseAfterFree.cc:5 РЕЗЮМЕ: AddressSanitizer: heap- use-after-free /home/test/example_UseAfterFree.cc:7 main Теневые байты вокруг ошибочного адреса: 0x0c287fff9f70: 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 0x0c287fff9fa0: 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 =>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 fd 0x0c287fff9fe0: fd 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 fd fa fa fa fa fa fa fa 0x0c fa fa fa fa000: fd 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 Легенда теневого байта (один теневой байт представляет 8 байтов приложения): Адресуемая: 00 Частично адресуемая: 01 02 03 04 05 06 07 Куча слева красная зона: fa Куча справа красная зона: fb Освобожденная область кучи: fd Стек левая красная зона: f1 Средняя красная зона стека: f2 Красная зона справа стек: f3 Частичная красная зона стека: f4 Стек после возврата: f5 Использование стека после области: f8 Глобальная красная зона: f9 Глобальный порядок инициализации: f6 Отравлен пользователем: f7 ASan internal: fe == 5587 == ABORTING

Heap-buffer-overflow

1 // RUN: clang ++ -O -g -fsanitize = address% t./a.out 2 int main (int argc, char ** argv) {3 int * array = new int [100]; 4 массив [0] = 0; 5 int res = массив [argc + 100]; // БУМ 6 удалить массив; 7 возвратных разрешений; 8}
== 25372 == ОШИБКА: AddressSanitizer: переполнение буфера-кучи по адресу 0x61400000ffd4 на ПК 0x0000004ddb59 bp 0x7fffea6005a0 sp 0x7fffea600598 ЧТЕНИЕ размера 4 на 0x61400000ffd4 thread T0 # 0x46 : 13 0x61400000ffd4 расположен на 4 байта справа от 400-байтовой области [0x61400000fe40,0x61400000ffd0), выделенной потоком T0 здесь: # 0 0x4536e1 в операторе delete (void *) # 1 0x46bfb9 в основном файле /tmp/main.cpp:2: 16

Stack-buffer-overflow

1 // ЗАПУСК: clang -O -g -fsanitize = адрес% t./a.out 2 int main (int argc, char ** argv) { 3 int stack_array [100]; 4 stack_array [1] = 0; 5 вернуть stack_array [argc + 100]; // BOOM 6}
== 7405 == ОШИБКА: AddressSanitizer: stack-buffer-overflow на адресе 0x7fff64740634 на компьютере 0x46c103 bp 0x7fff64740470 sp 0x7fff64740468 ЧИТАТЬ размера 4 на 0x7fff64740634 потоке T07fff64740634 в примере. cc: 5 Адрес 0x7fff64740634 расположен в стеке потока T0 по смещению 436 в кадре # 0 0x46bfaf в основном /tmp/example_StackOutOfBounds.cc:2 Этот кадр имеет 1 объект (ы): [32, 432) 'stack_array' <== Memory access at offset 436 overflows this variable

Глобальное переполнение буфера

// ЗАПУСК: clang -O -g -fsanitize = адрес% t./a.out int global_array [100] = {-1}; int main (int argc, char ** argv) {return global_array [argc + 100]; // BOOM}
== 7455 == ОШИБКА: AddressSanitizer: global-buffer-overflow на адресе 0x000000689b54 на ПК 0x46bfd8 bp 0x7fff515e5ba0 sp 0x7fff515e5b98 ЧИТАТЬ размером 4 на 0x000000689b54 thread T0fd7 / 0x : 4 0x000000689b54 находится в 4 байтах справа от глобальной переменной global_array из example_GlobalOutOfBounds.cc (0x6899c0) размером 400
Ограничения

AddressSanitizer не обнаруживает никаких операций чтения из неинициализированной памяти ( но это обнаруживается), и обнаруживает только некоторые ошибки использования после возврата. Он также не способен обнаруживать все ошибки произвольного повреждения памяти или все ошибки произвольной записи из-за целочисленного переполнения / переполнения (когда целое число с неопределенным поведением используется для вычисления смещения адресов памяти). Смежные буферы в структурах и классах не защищены от переполнения, отчасти для предотвращения нарушения обратной совместимости.

См. Также
Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-10 00:18:00
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте