Проблема здесь:
strncpy(buffer,str,strlen(str));
^^^^^^^^^^^
Если строка превышает длину целевого буфера, strncpy все равно скопирует ее. Вы основываете количество символов строки в качестве числа для копирования вместо размера буфера. Правильный способ сделать это заключается в следующем:
strncpy(buffer,str, sizeof(buff) - 1);
buffer[sizeof(buff) - 1] = '\0';
Это ограничивает объем копируемых данных фактическим размером буфера минус один для нулевого завершающего символа. Затем мы устанавливаем последний байт в буфере нулевым символом в качестве дополнительной защиты. Причина этого в том, что strncpy будет копировать до n байтов, включая завершающий ноль, если strlen (str) <len - 1. Если нет, то ноль не копируется, и у вас есть сценарий сбоя, потому что теперь ваш буфер имеет неопределенный строка.
Надеюсь это поможет.
РЕДАКТИРОВАТЬ: После дальнейшего изучения и ввода от других, возможное кодирование для функции следующим образом:
int func (char *str)
{
char buffer[100];
unsigned short size = sizeof(buffer);
unsigned short len = strlen(str);
if (len > size - 1) return(-1);
memcpy(buffer, str, len + 1);
buffer[size - 1] = '\0';
return(0);
}
Поскольку мы уже знаем длину строки, мы можем использовать memcpy, чтобы скопировать строку из местоположения, на которое ссылается str, в буфер. Обратите внимание, что на странице руководства для strlen (3) (в системе FreeBSD 9.3) указано следующее:
The strlen() function returns the number of characters that precede the
terminating NUL character. The strnlen() function returns either the
same result as strlen() or maxlen, whichever is smaller.
Который я интерпретирую как то, что длина строки не включает ноль. Вот почему я копирую len + 1 байт, чтобы включить ноль, и тест проверяет, чтобы убедиться, что длина <размер буфера - 2. Минус один, потому что буфер начинается с позиции 0, и минус другой, чтобы убедиться, что есть место для нуля.
РЕДАКТИРОВАТЬ: Оказывается, размер чего-то начинается с 1, а доступ начинается с 0, так что -2 раньше был неправильным, потому что он вернул бы ошибку для всего> 98 байтов, но это должно быть> 99 байтов.
РЕДАКТИРОВАТЬ: Хотя ответ о беззнаковых коротких, как правило, является правильным, так как максимальная длина, которая может быть представлена, составляет 65 535 символов, это на самом деле не имеет значения, потому что если строка длиннее, значение будет перенесено. Это все равно, что взять 75 231 (что 0x000125DF) и замаскировать верхние 16 бит, что даст вам 9695 (0x000025DF). Единственная проблема, с которой я сталкиваюсь, это первые 100 символов после 65 535, поскольку проверка длины разрешит копирование, но во всех случаях будет копироваться только до первых 100 символов строки, и нулевое завершение строки . Таким образом, даже в случае проблемы с переносом, буфер все равно не будет переполнен.
Это может или не может само по себе представлять угрозу безопасности в зависимости от содержимого строки и того, для чего вы ее используете. Если это просто прямой текст, который читается человеком, то обычно проблем нет. Вы просто получаете усеченную строку. Однако, если это что-то вроде URL или даже последовательности команд SQL, у вас могут возникнуть проблемы.