Какие функции C / C ++ чаще всего используются неправильно и могут привести к переполнению буфера? - PullRequest
16 голосов
/ 03 октября 2008

Меня попросили поддерживать большую кодовую базу C ++, полную утечек памяти. Разглядывая, я обнаружил, что у нас много переполнений буфера, которые приводят к утечкам (как это стало плохо, я никогда не хочу знать).

Я решил сначала удалить переполнения буфера, начиная с опасных функций. Какие функции C / C ++ чаще всего используются некорректно и могут привести к переполнению буфера?

Для компилятора и / или инструментов, используемых для поиска переполнения буфера, я создал еще один вопрос, связанный с этим

Ответы [ 11 ]

11 голосов
/ 03 октября 2008

В общем, любая функция, которая не проверяет границы в аргументах. Список будет

  • получает ()
  • зсапЕ ()
  • зЬгср ()
  • strcat ()

Вы должны использовать версии с ограниченным размером, такие как stncpy, strncat, fgets и т. Д. Затем будьте осторожны, задавая ограничение размера; принять во внимание, что '\ 0' завершает строку.

Кроме того, массивы НЕ проверяются на привязку в C или C ++. Следующий пример может вызвать ошибки. См. отключено на одну ошибку

int foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

edit : Скопированные ответы @MrValdez, @Denton Gentry

5 голосов
/ 03 октября 2008

Valgrind - ваш новый лучший друг.

valgrind --tool = memcheck --leak-check = full ./a.out

3 голосов
/ 03 октября 2008

Боюсь, вопрос начинается не с того конца. Предполагается, что переполнение буфера происходит в других функциях. По моему опыту, наиболее частой причиной является оператор ++ или отсутствие оператора! =.

Лучшее решение для поиска пакета - это / GS в Visual Studio 2005/8. Он не найдет их всех, но это дешевый способ уменьшить количество ручной работы.

2 голосов
/ 03 октября 2008

У меня примерно такая же проблема с базой кода, над которой я работаю. Мой совет: будьте осторожны с любыми функциями C, которые выглядят как str * () и mem * (). Также будьте осторожны со всем, что принимает указатель на буфер, без длины. Поскольку кажется, что у вас есть шанс использовать C ++, я бы в самых вопиющих случаях попытался использовать контейнеры C ++ для вещей: вектор, строка, карта и т. Д. Это значительно облегчает вашу жизнь.

Кроме того, инструменты автоматического обнаружения проблем просто замечательны. Если вы можете использовать valgrind, я бы порекомендовал его. Также Rational Purify является чрезвычайно мощным, хотя и не дешевым.

2 голосов
/ 03 октября 2008

Какую версию visual studio вы используете? В 2008 году со всеми включенными предупреждениями все функции, о которых вы упоминаете (и даже больше), предупреждают вас об их устаревании.

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

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

2 голосов
/ 03 октября 2008

Memcpy () является еще одним опасным.

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

Утечки памяти вызваны выделением памяти, а не ее освобождением. Конструктор и деструкторы должны быть еще одним сильным аргументом в пользу того, чтобы убедиться, что любая выделенная память освобождена.

2 голосов
/ 03 октября 2008

К сожалению, любой массив может привести к переполнению буфера:

uint32_t foo[3];
foo[3] = WALKED_OFF_END_OF_ARRAY;

С точки зрения функций, sprintf с удовольствием уйдет с конца буфера. Его можно заменить на snprintf.

2 голосов
/ 03 октября 2008

Следующая ссылка должна дать вам полный обзор функций безопасности в C ++ (те, которые пост-исправлены с '_s', чтобы исправить проблемы, такие как переполнения): http://msdn.microsoft.com/en-us/library/8ef0s5kh(VS.80).aspx

РЕДАКТИРОВАТЬ: Эта ссылка содержит конкретные функции, которые были заменены: http://msdn.microsoft.com/en-us/library/wd3wzwts(VS.80).aspx

РЕДАКТИРОВАТЬ: Я должен упомянуть, что это методы Microsoft, но ссылка по-прежнему полезна для определения функций, которые считались красным флагом.

2 голосов
/ 03 октября 2008

Вот некоторые функции, которые я нашел опасными:

  • gets () - Он не проверяет длину переменной и может перезаписывать память, если ввод больше, чем буфер переменной.
  • scanf () - я так рад, что Visual Studio сказала, что эта функция устарела. Это было легко исправить.
  • strcpy () - Если пространство памяти источника больше, чем место назначения, данные после места назначения перезаписываются.
1 голос
/ 08 июня 2009

Дополнительным плюсом в C является функция "strncpy ()". Многие люди не понимают, что можно свободно возвращать строку, которая не заканчивается нулем.

...