Почему электрический забор /Valgrind не может уловить проблему переполнения буфера?
Я создал программу с ошибками - buggy.c - это сценарий переполнения буфера для буфера t. Вы можете видеть, что я пишу более 5 индексов. Работает нормально. Это никогда не бросает мне ошибку. Мне было интересно, почему это так? Я пробовал даже Valgrind, это также не может найти эту проблему. Подскажите, пожалуйста, в чем здесь проблема?
void buffer_overflow(void)
{
int t[5];
int i = 0;
for(i = 0; i<=7; i++)
{
t[i] = i;
}
/** this will cause buffer overflow **/
printf("Memory_overflow_completed\r\n");
}
int main(int argc, char **argv)
{
buffer_overflow();
return 0;
}
$gcc -g buggy.c -o buggy.out -lefence
$./buggy.out
Тем не менее, я не получаю никакого сбоя. Здесь нет эффекта электрического забора. Что мне не хватает? Я видел, что подобный вопрос, размещенный здесь, gcc с библиотекой электрического забора не вступает в силу, но, похоже, ответа пока нет. Я запускаю этот пример на FC19. У кого-нибудь есть ответ на это? Даже Valgrind не может обнаружить проблему? Есть ли другой инструмент для обнаружения этих проблем?
Основываясь на дальнейших комментариях, я пересмотрел функцию переполнения буфера, чтобы она была обнаружена Electric Fence. Однако Electric Fence не может обнаружить проблему. Вот модифицированная функция.
void buffer_overflow(void)
{
#if 0
int t[5];
int i = 0;
for(i = 0; i<=7; i++)
{
t[i] = i;
}
#endif
char *t = malloc(sizeof(char)*7);
strcpy(t,"SHREYAS_JOSHI");
/** this will cause buffer overflow **/
printf("Memory_overflow_completed\r\n");
free(t);
}
[joshis1@localhost blogs-tune2wizard]$ gcc -g buggy.c -o buggy.out -lefence
[joshis1@localhost blogs-tune2wizard]$ ./buggy.out
Electric Fence 2.2.2 Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
Memory_overflow_completed
Electric Fence не обнаружил никаких ошибок, но Valgrind по крайней мере показал это.
5 ответов
Valgrind ограничен наличием только двоичного файла. Если вы не возражаете против того, чтобы в ваш код был вставлен какой-либо инструментарий (компилятором), вы можете попробовать очиститель адресов. Он отравляет память вокруг выделенных областей (даже в стеке), а затем проверяет каждое чтение / запись, поэтому у него больше шансов обнаружить эти проблемы.
Он интегрирован в текущие gcc (4.8+) и clang (3.2+). Просто скомпилируйте ваш код следующим образом:
gcc -g buggy.c -o buggy.out -fsanitize=address
После выполнения он печатает что-то вроде:
==26247== ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff9fa0be54 at pc 0x4008df bp 0x7fff9fa0be00 sp 0x7fff9fa0bdf8
WRITE of size 4 at 0x7fff9fa0be54 thread T0
и трассировка стека.
Чендлер Кэррут говорил об этом в этом выступлении на GN13
Примечание: поддерживается даже в clang 3.1, но коммутатор называется -faddress-sanitizer
вместо -fsanitize=address
,
Бег valgrind --tool=exp-sgcheck ./buggy.out
и он должен быть в состоянии обнаружить, что у вас переполнение буфера в локальной переменной t[5]
Valgrind и EF обнаруживают ошибки в динамически выделяемой памяти. Ваш массив не распределяется динамически.
Цитирование из справочника по быстрому запуску valgrind: "Например, он не может обнаружить чтение или запись вне диапазона для массивов, которые размещены статически или в стеке".
Чтобы обнаружить за пределами доступа в статически выделенной памяти (то есть в стеке), вы можете использовать инструмент статического анализа кода.
Klocwork, который мы только начали использовать на работе
Как упомянуто на вики-странице Valgrind (в рамках ограничений memcheck), он не может обнаруживать вне доступа к статически выделенной памяти. Цитата из вики:
Экспериментальный инструмент valgrind exp-sgcheck был написан для устранения этого ограничения в Memcheck. Он обнаружит ошибки переполнения массива при условии, что первый доступ к массиву находится в границах массива.