Почему электрический забор /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. Он обнаружит ошибки переполнения массива при условии, что первый доступ к массиву находится в границах массива.

Другие вопросы по тегам