Несколько дезинфицирующих средств (из GCC или Clang) нельзя комбинировать — т. е. использовать одновременно в одной сборке, но Asan и Ubsan можно комбинировать — т. е. я могу собрать с «-fsanitize=address,undefined -fsanitize-recover=all…» и иметь исполняемый файл, который выполняет проверки обоих дезинфицирующих средств. Пока все хорошо.
Однако LOGGING из полученного исполняемого файла кажется проблематичным.
Во всех случаях, если в параметрах не задан «log_path», обо всех дефектах сообщается на stderr. ОК пока. Однако попробуйте использовать log_path, и все станет странно:
- Для исполняемого файла, созданного только с помощью Asan, и для параметра ASAN_OPTIONS, включающего «log_path=./ASAN», дефекты Address Saniitizer попадут в файл с именем ASAN.
- Для исполняемого файла, созданного только с помощью Ubsan, и для параметра UBSAN_OPTIONS, включающего «log_path=./UBSAN», дефекты неопределенного поведения будут помещены в файл с именем UBSAN.
- Для исполняемого файла, созданного как с Asan, так и с Ubsan o Выходные данные Asan идут в указанный файл журнала, но выходные данные ubsan идут только в stderr o Вышеприведенное применимо, даже если log_path установлен только через UBSAN_OPTIONS, а ASAN_OPTIONS не установлен o Если log_path установлен установлен как в ASAN_OPTIONS, так и в UBSAN_OPTIONS, используемый log_path является UBSAN, но содержит только результаты ASAN
Есть ли какая-то скрытая магия, позволяющая обоим дезинфицирующим средствам записывать в один и тот же журнал дефектов?
Чтобы воспроизвести, используйте простой тестовый пример, в котором есть дефект для каждого дезинфицирующего средства:
char *hello = "hello";
int main (int argc, char *argv[])
{
int x = 1;
x <<= 32; // Error: (1 << 32) can't be represented in a (32-bit) int
char some_char = hello [argc *10];
}
построить и запустить: (здесь используется g++ 7.3.0, но другие версии GCC, а также clang 7.1.0 показали такое же базовое поведение)
Только асан - работает как положено
g++ foo.C -fsanitize=address -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out
Файл АСАН. 29648 содержит дефект, начинающийся с
== 29648 == ОШИБКА: AddressSanitizer: глобальное переполнение буфера по адресу 0x000000400aca на ПК 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088
ЧТЕНИЕ размера 1 в 0x000000400aca thread T0 0x4009a4 в main /tmp/foo.C:7
Только Убсан - работает как положено
g++ foo.C -fsanitize=undefined -fsanitize-recover=all -g
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out
Файл UBSAN.29675 содержит
foo.C:6:6: ошибка выполнения: экспонента сдвига 32 слишком велика для 32-битного типа 'int'
Asan PLUS Ubsan - странное поведение при регистрации
g++ foo.C -fsanitize=address,undefined -fsanitize-recover=all -g
setenv ASAN_OPTIONS "log_path=./ASAN:halt_on_error=0:handle_abort=1:exitcode=0"
a.out
ASAN_OPTIONS игнорируется, обо всех дефектах сообщается в stderr. Теперь попробуйте установить UBSAN_OPTIONS:
setenv UBSAN_OPTIONS "log_path=./UBSAN:halt_on_error=0:handle_abort=1:exitcode=0”
a.out
Файл UBSAN.30352 содержит ТОЛЬКО дефект Asan:
==30352==ОШИБКА: AddressSanitizer: глобальное переполнение буфера по адресу 0x000000400aca на компьютере 0x0000004009a5 bp 0x7fffffffe090 sp 0x7fffffffe088 ЧТЕНИЕ размера 1 по адресу 0x000000400aca thread T0 0x4009a4 в main /tmp7foo.C:tmp7foo.C:tmp7foo.C:tmp7foo.C:
а дефект Ubsan записывается только в stderr:
foo.C:6:6: ошибка выполнения: экспонента сдвига 32 слишком велика для 32-битного типа 'int'