Как найти (все) целочисленные переполнения в C-программе? - PullRequest
15 голосов
/ 04 января 2011

Я работаю над большим проектом, который обычно работает просто отлично, но показывает серьезные проблемы, когда размер входных данных превышает некоторые ограничения.

Эти проблемы (предположительно) возникают только из-за целочисленных переполнений со знаком, таких как:

int a, o;
// Initialize a and o
int x = (a+o) >> 1);

Очевидно, что как только сумма a и o переполняется (становится больше, чем 2 ^ 31-1), x больше не является средним значением a и o.

Есть ли общий способ найти все эти целочисленные переполнения в работающей программе?

Я имею в виду такой инструмент, как Valgrind или расширение GDB, которое ломается при каждой целочисленной арифметической инструкции, принимает параметры и сравнивает правильный результат (рассчитанный с типом данных большего размера или арифметикой произвольной точности) с фактическим результатом. Если результаты отличаются, он должен вывести предупреждение, вызвать прерывание отладки или что-то вроде этого.

Я знаю, как проверить одну арифметическую инструкцию на переполнение (например, проверить знак для дополнений), однако из-за огромного количества кода для меня нереально решить весь проект и вставить проверочный код везде от руки.

Ответы [ 3 ]

3 голосов
/ 04 января 2011

Для большой базы кода, Coverity - хороший инструмент.Я не уверен, что он обнаружит all целочисленные переполнения или нет, но стоит попробовать.

2 голосов
/ 04 января 2011

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

Поскольку приведенный вами пример не работает для отрицательных значений, вы все равно должны использовать unsigned int, что уже дает вам дополнительный порядок.

Edit: У gcc есть опция -ftrapv, но этот обычно ничего не делает работает только с -O0. Если вы используете метод перехвата ловушек, когда они происходят, вам все равно нужно хорошее знание кода, чтобы полностью его протестировать.

0 голосов
/ 04 января 2011

Как насчет скрипта, который проходит через код и заменяет все "a + b" на DEBUGADD (a, b) - где вы можете сделать:

#ifdef DEBUG
int addFn(int a, int b) {
  long long m;
  int n;
  m = (long long)a + (long long)b;
  n = a + b;
  if (m != (long long)n)
    printf("PANIC!\n");
  return n;
}
#define DEBUGADD(a,b) addFn(a,b)
#else
#define DEBUGADD(a,b) ((a)+(b))
#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...