Я создал программу с ошибками — 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 <[email protected]>
Memory_overflow_completed
Electric Fence не обнаружил никаких ошибок, но Valgrind по крайней мере показал это.
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 обнаруживают ошибки в динамически выделяется объем памяти. Ваш массив не распределяется динамически.
Цитирование из Вальгринда Инструкция по началу работы: «Например, он не может обнаружить чтение или запись вне диапазона для массивов, которые размещены статически или в стеке».
Чтобы обнаружить за пределами доступа в статически выделенной памяти (то есть в стеке), вы можете использовать инструмент статического анализа кода.
Тот, который мы только начали использовать на работе Klocwork
Как уже упоминалось на Valgrind вики-страница (в рамках ограничений memcheck), он не может обнаружить доступ из-за ограничений на статически выделенную память.
Цитата из вики:
Экспериментальный инструмент valgrind exp-sgcheck был написан для устранения этого ограничения в Memcheck. Он обнаружит ошибки переполнения массива при условии, что первый доступ к массиву находится в границах массива.