Обнаружение переполнения строки в C - PullRequest
3 голосов
/ 24 февраля 2010

Мы используем DevPartners для проверки утечки памяти. Он делает замечательную работу, хотя и не находит переполнения строк, как показано ниже

char szTest [1] = "";

for (i = 0; i < 100; i ++) {

    strcat (szTest, "hi");
}

Вопрос-1: Есть ли какой-нибудь способ, которым я могу заставить BoundsChecker это обнаружить?

Вопрос-2: Есть ли у них какой-либо другой инструмент, способный обнаруживать такие проблемы?

Ответы [ 8 ]

2 голосов
/ 24 февраля 2010

Я попробовал это в моем devpartner (msvc6.6) (devpartner 7.2.0.372)

Я подтверждаю ваше наблюдаемое поведение.Я получаю нарушение прав доступа после примерно 63 проходов цикла.

Что Compuware может сказать о проблеме?

CppCheck обнаружит эту проблему.

2 голосов
/ 24 февраля 2010

valgrind обнаружит запись прошлых динамически распределенных данных, но я не думаю, что это может быть сделано для автоматических массивов, как в вашем примере. Если вы используете strcat, strcpy и т. Д., Вы должны убедиться, что пункт назначения достаточно большой.

Редактировать : Я был прав насчет Вальгринда , но есть надежда:

К сожалению, Memcheck не выполняет проверку границ статических или стековых массивов. Мы бы хотели, но это просто невозможно сделать разумным образом, который бы соответствовал принципам работы Memcheck. К сожалению.

Однако экспериментальный инструмент Ptrcheck может обнаруживать подобные ошибки. Запустите Valgrind с опцией --tool=exp-ptrcheck, чтобы попробовать его, но помните, что он не такой надежный, как Memcheck.

Я не использовал Ptrcheck.

2 голосов
/ 24 февраля 2010

Один из вариантов - просто запретить использование строковых функций, которые не имеют информации о буфере назначения. Может быть полезен набор макросов, подобных следующему в универсально включенном заголовке:

#define strcpy  strcpy_is_banned_use_strlcpy
#define strcat  strcat_is_banned_use_strlcat
#define strncpy strncpy_is_banned_use_strlcpy
#define strncat strncat_is_banned_use_strlcat
#define sprintf sprintf_is_banned_use_snprintf

Таким образом, любая попытка использования «запрещенных» подпрограмм приведет к ошибке компоновщика, которая также скажет вам, что вы должны использовать вместо этого. MSVC сделал нечто подобное, что можно контролировать с помощью макросов, таких как _CRT_SECURE_NO_DEPRECATE.

Недостаток этого метода заключается в том, что если у вас большой набор существующего кода, то может оказаться трудной задачей перенести вещи на использование новых, более безопасных процедур. Это может свести вас с ума, пока вы не избавитесь от функций, считающихся опасными.

1 голос
/ 24 февраля 2010

Если вы включите параметр компилятора / RTCs, это может помочь в обнаружении подобных проблем. С этим включением тест вызвал нарушение прав доступа при запуске strcat только один раз.

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

1 голос
/ 24 февраля 2010

Учитывая, что вы пометили этот C ++, зачем вообще использовать указатель на char?

std::stringstream test;
std::fill_n(std::ostream_iterator<std::string>(test), 100, "hi");
1 голос
/ 24 февраля 2010

Возможно, вам поможет ваш компилятор. Например, в Visual Studio 2008 проверьте свойства проекта - C / C ++ - Страница генерации кода. Есть опция «Проверка безопасности буфера».

Я думаю, что он резервирует немного дополнительной памяти и записывает в нее известную последовательность. Если эта последовательность изменяется, она предполагает переполнение буфера. Я не уверен, хотя - я помню, что читал это где-то, но я точно не помню, было ли это про VC ++.

0 голосов
/ 07 апреля 2011

Проблема заключалась в том, что по умолчанию подсистема проверки API не включена, и сообщения, которые вас интересовали, приходят оттуда.

Я не могу говорить о более старых версиях BoundsChecker, но у версии 10.5 нет особых проблем с этим тестом. Он сообщает правильные результаты и сам BoundsChecker не дает сбоя. Однако тестовое приложение делает это, потому что этот конкретный тестовый случай полностью повреждает стек вызовов, который привел к функции, в которой находился тестовый код, и как только эта функция завершается, приложение также делает это.

Результаты: 100 сообщений о переполнении записи в локальную переменную и 99 сообщений о том, что строка назначения не обнуляется. Технически, это второе сообщение неверно, но BoundsChecker ищет только нулевое завершение в границах самой строки назначения, и после первого вызова strcat оно больше не содержит нулевой байт в своих границах.

Отказ от ответственности: я работаю в MicroFocus как разработчик, работающий над BoundsChecker.

0 голосов
/ 11 марта 2011

Альтернатива: наша Проверка безопасности памяти .Я думаю, что он справится с этим делом.

...