AddressSanitizer в ROSA Fresh — различия между версиями

Материал из Rosalab Wiki
Перейти к: навигация, поиск
(Added packaging notes)
Строка 9: Строка 9:
 
Лучше всё делать на 64-битной системе. AddressSanitizer удавалось запустить и на 32-битной системе, а вот ThreadSanitizer работает только на 64-битных.  
 
Лучше всё делать на 64-битной системе. AddressSanitizer удавалось запустить и на 32-битной системе, а вот ThreadSanitizer работает только на 64-битных.  
  
Для работы с AddressSanitizer потребуются следующие пакеты: lib64asan0 и lib64asan-devel.
+
Для работы с AddressSanitizer потребуются следующие пакеты: lib64asan0 и lib64asan-devel.  
  
 
Рассмотрим такой пример:
 
Рассмотрим такой пример:
Строка 105: Строка 105:
  
 
Одновременно использовать оба инструмента (то есть задавать и ''-fsanitize=thread'', и ''-fsanitize=address'') не рекомендуется.
 
Одновременно использовать оба инструмента (то есть задавать и ''-fsanitize=thread'', и ''-fsanitize=address'') не рекомендуется.
 +
 +
== Сборка пакетов ==
 +
 +
Если нужно собрать пакет, для приложений и библиотек из которого при сборке включается AddressSanitizer или ThreadSanitizer, в .spec-файл надо добавить <code>BuildRequires: asan-devel</code> или <code>BuildRequires: tsan-devel</code>, соответственно.
  
 
== TODO ==
 
== TODO ==

Версия 10:32, 11 августа 2014

В GCC 4.8 появились новые полезные инструменты для поиска ошибок в приложениях, в частности:

Ещё раньше такие инструменты появились для LLVM/Clang.

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

Лучше всё делать на 64-битной системе. AddressSanitizer удавалось запустить и на 32-битной системе, а вот ThreadSanitizer работает только на 64-битных.

Для работы с AddressSanitizer потребуются следующие пакеты: lib64asan0 и lib64asan-devel.

Рассмотрим такой пример:

/* test.c */
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int 
 5 main(int argc, char *argv[])
 6 {
 7 	int *p = malloc(10 * sizeof(int));
 8 	if (!p)
 9 		return 1;
10 	
11 	printf("Hello, World!\n");
12 	printf("Data: %d\n", p[10]); /// < Выход за границы блока памяти.
13 	return 0;
14 }

При сборке приложения нужно добавить опцию компилятора -fsanitize=address и слинковать приложение с библиотекой libasan. Стоит также включить генерацию отладочной информации. Оптимизацию можно не отключать.

gcc -g -O2 -fsanitize=address -o test test.c -lasan

Если теперь запустить полученное приложение, будет выдано следующее:

$ ./test
Hello, World!
=================================================================
==16996== ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60080000bff8 at pc 0x40095c bp 0x7fffe698dc60 sp 0x7fffe698dc58
READ of size 4 at 0x60080000bff8 thread T0
    #0 0x40095b (/home/user/work/asan_examples/test+0x40095b)
    #1 0x7fee4a59b744 (/lib64/libc-2.15.so+0x21744)
    #2 0x4007f8 (/home/user/work/asan_examples/test+0x4007f8)
0x60080000bff8 is located 0 bytes to the right of 40-byte region [0x60080000bfd0,0x60080000bff8)
allocated by thread T0 here:
    #0 0x7fee4a94854a (/usr/lib64/libasan.so.0.0.0+0x1554a)
    #1 0x400900 (/home/user/work/asan_examples/test+0x400900)
    #2 0x7fee4a59b744 (/lib64/libc-2.15.so+0x21744)
Shadow bytes around the buggy address:
  0x0c017fff97a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff97b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff97c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff97d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff97e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c017fff97f0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x0c017fff9800:fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff9810: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff9820: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff9830: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c017fff9840: 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 righ 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
==16996== ABORTING

То есть AddressSanitizer выявил некорректную операцию чтения из памяти. Инструкция, которая её выполнила, находилась по адресу 0x40095b (/home/user/work/asan_examples/test+0x40095b). Блок памяти был выделен здесь: 0x400900 (/home/user/work/asan_examples/test+0x400900).

Так как анализируемое приложение содержит отладочную информацию, можно определить и то, каким строкам исходного кода соответствуют эти адреса:

$ addr2line -e test -i 0x40095b
/home/user/work/asan_examples/test.c:12

$ addr2line -e test -i 0x400900
/home/user/work/asan_examples/test.c:7

Для использования ThreadSanitizer нужно выполнить похожие операции. Потребуются пакеты lib64tsan0 и lib64tsan-devel. Анализируемое приложение надо собирать так:

gcc -g -fPIC -fsanitize=thread -o test test.c -pie -ltsan

Без -fPIC и -pie сборка может не пройти.

Одновременно использовать оба инструмента (то есть задавать и -fsanitize=thread, и -fsanitize=address) не рекомендуется.

Сборка пакетов

Если нужно собрать пакет, для приложений и библиотек из которого при сборке включается AddressSanitizer или ThreadSanitizer, в .spec-файл надо добавить BuildRequires: asan-devel или BuildRequires: tsan-devel, соответственно.

TODO

В GCC 4.9 появились также инструменты для поиска утечек памяти (LeakSanitizer, LSan) и ситуаций с неопределённым поведением (Undefined Behaviour Sanitizer, UBSan). Привести примеры, описать, как с этим работать.