Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

Чтение данных через сетевое соединение предоставляет еще одну возможность для переполнения буфера. Многие сетевые протоколы указывают максимальный размер для полей данных. Например, протокол ВООТР [160] фиксирует для всех пакетов размер 300 байтов. Это, однако, не мешает другой машине передать через сеть 350-байтовый пакет ВООТР. Если в сети работают программы с дефектами, то они попытаются скопировать этот нестандартный 350-байтовый пакет в пространство, выделенное для корректного 300-байтового пакета ВООТР, тем самым вызовут переполнение буфера.

160

ВООТР — это предшественник DHCP, позволяющий компьютерам автоматически узнавать свои IP-адреса при запуске сетевых интерфейсов.

Локализация и трансляция служат еще двумя побудителями переполнения буфера. Если программа написана для английского языка, то без сомнения для хранения названия месяца, загружаемого из таблицы, будет достаточно десятисимвольной строки. Когда эта программа переводится на испанский, "September" превращается в "Septiembre" и может произойти переполнение буфера. Всякий раз, когда программа поддерживает различные языки и локали, большинство первоначально статических строк становятся динамическими, и внутренние строковые буферы должны это учитывать.

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

_POSIX_PATH_MAX
?), и этим чрезвычайно легко воспользоваться.

Существует несколько приемов для устранения из кода возможности переполнения буфера. Хорошо продуманные программы используют множество способов для внимательного выделения буферов соответствующих размеров.

Лучшим способом распределения памяти для объектов является метод

malloc
, который устраняет проблемы, возникающие из-за перезаписывания возвращаемого адреса, поскольку
malloc
не выделяет память из стека. Аккуратное применение функции
strlen
для вычисления необходимого размера и динамическое выделение буфера в программной куче обеспечивает хорошую защиту от переполнения. К сожалению, при этом также расходуется память, поскольку каждый вызов метод
malloc
требует вызова метода
free
. В главе 7 обсуждалось несколько способов отслеживания ненужных расходов памяти, однако даже с описанными инструментами трудно точно знать, когда можно освободить память, занимаемую объектом. Особенно в том случае, если динамическое распределение памяти для объекта подстроено под уже существующий код. Функция
alloca
предлагает альтернативу
malloc
.

#include <alloca.h>

void * alloca(size_t size);

Подобно

malloc
,
alloca
выделяет область памяти длиной
size
байтов и возвращает указатель на начало этой области. Вместо использования памяти из программной кучи этот метод распределяет память из вершины стека, из того же места, где хранятся локальные переменные. Первое преимущество данной функции перед локальными переменными состоит в том, что необходимое количество байтов точно вычисляется в программе, а не определяется приблизительно. Превосходство над
malloc
заключается в том, что при завершении работы функции память освобождается автоматически. Все это позволяет охарактеризовать
alloca
как легкий способ распределения памяти, которая требуется только временно. До тех пор, пока размер буфера вычисляется должным образом (не забудьте учесть
'\0'
в конце каждой строки С!), можно не бояться переполнения буфера [161] .

161

Функция

alloca
не является стандартным средством языка С, однако компилятор gcc предоставляет
alloca
в большинстве поддерживаемых операционных систем. В более старых версиях gcc (до версии 3.3)
alloca
не всегда должным образом взаимодействовала с массивами динамических размеров (другое расширение GNU), поэтому примите во внимание, что использовать нужно только одну из версий.

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

strncpy
и
strncat
легко предотвращают перегрузки буфера при копировании строк.

#include <string.h>

char * strncpy (char * dest, const char * src, size_t max);

char * strncat (char * dest, const char * src, size_t max);

Обе функции ведут себя как их родственники, называемые аналогично,

strcpy
и
strcat
, но они возвращают за один раз только max байт, копируемые в строку назначения. Если достигнут предел, то результирующая строка не завершается
'\0'
, поэтому обычные строковые функции не смогут с ней работать. По этой причине необходимо явно завершить строку после вызова одной из подобных функций.

strncpy(dest, src, sizeof(dest));

dest[sizeof(dest) - 1] = '\0';

Частой ошибкой при использовании

strncat
является передача общего размера
dest
в качестве параметра
max
. Это приводит к потенциальному переполнению буфера, так как
strncat
добавляет до
max
байт в
dest
; она не прекращает копировать байты, когда общая длина
dest
достигает
max
байтов.

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

Функция

strncpy
решает проблему копирования строки в статический буфер без переполнения его. А функции
strdup
автоматически выделяют буфер, достаточный для хранения строки, до начала копирования в него исходной строки.

#include <string.h>

char * strdup(const char * src);

char * strdupa(const char * src);

char * strndup(const char * src, int max);

char * strndupa(const char * src, int max);

  • Читать дальше
  • 1
  • ...
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: