По соглашению, функции стандартной библиотеки C определяют конец строки по нулевому байту. Например функция strcpy(3) копирует содержимое исходной строки в строку назначения пока не встретит нулевой байт. В некоторых случаях такое поведение становится опасным; мы видели, что следующий код содержит дыру в безопасности:
#define LG_IDENT 128
int fonction (const char * name)
{
char identity [LG_IDENT];
strcpy (identity, name);
...
}
Функции, ограничивающие длину копирования, обходят эту проблему. Эти функции имеют букву `n' в середине их названий, например, strncpy(3) как замена для strcpy(3), strncat(3) для strcat(3) или даже strnlen(3) для strlen(3).
Однако, вы должны быть осторожными с использованием ограничения функции strncpy(3), так как оно порождает краевой эффект: когда исходная строка меньше строки назначения, копия будет дополнена нулевыми символами до n-ой позиции, что делает приложение медленее. С другой стороны, если исходная строка длиннее, она будет урезана и копия поэтому не будет заканчиваться нулевым символом. Поэтому вы должны добавить его вручную. Принимая это во внимание, предыдущая подпрограмма приобретает вид:
Естественно, те же принципы применимы и к процедурам работы с "широкими" символами (более 8 бит), например wcsncpy(3) нужно отдать предпочтение над wcscpy(3) или wcsncat(3) над wcscat(3). Конечно, программа становится больше, но также повышается и безопасность.
Как и strcpy(), strcat(3) не проверяет размер буфера. Функция strncat(3) добаляет символ в конец строки, если там еще есть место для этого. Замена strcat(buffer1, buffer2); на strncat(buffer1, buffer2, sizeof(buffer1)-1); исключает риск.
Функия sprintf() позволяет копировать форматированные данные в строку. У нее также есть версия, которая может проверять количество байт для копирования: snprintf(). Данная функция возвращает количество записанных символов в строку назначения (без учета '\0'). Проверка этого возвращаемого значения скажет вам, было ли произведено копирование должным образом:
Очевидно, все это не стоит затраченного труда, если пользователь получает контроль над числом байт для копирования. Подобная дыра в BIND (Berkeley Internet Name Daemon) дала работу большому числу взломщиков:
Это всегда будет копировать 4 байта. И все-таки, если вы можете изменять hp->h_length, тогда вы можете изменять стек. Соответственно, обязательна проверка длины данных перед копированием:
В некоторых случаях, нельзя обрезать строку таким образом (путь, имя машины, URL, ...), обработка таких случаев должна производиться в программе раньше, как только введены данные.