Как я могу использовать strncat без проблем переполнения буфера? - PullRequest
9 голосов
/ 02 августа 2011

У меня есть буфер, я делаю много strncat. Я хочу убедиться, что я никогда не переполняю размер буфера.

char buff[64];

strcpy(buff, "String 1");

strncat(buff, "String 2", sizeof(buff));

strncat(buff, "String 3", sizeof(buff));

Вместо sizeof (бафф) я хочу сказать что-то бафф - ххх. Я хочу убедиться, что я никогда не перезаписываю буфер

Ответы [ 5 ]

16 голосов
/ 02 августа 2011

Примите во внимание размер существующей строки и нулевой терминатор

#define BUFFER_SIZE 64
char buff[BUFFER_SIZE];

//Use strncpy
strncpy(buff, "String 1", BUFFER_SIZE - 1);
buff[BUFFER_SIZE - 1] = '\0';

strncat(buff, "String 2", BUFFER_SIZE - strlen(buff) - 1);

strncat(buff, "String 3", BUFFER_SIZE - strlen(buff) - 1);
11 голосов
/ 02 августа 2011

Почему бы не использовать snprintf?В отличие от strncat он ожидает размер буфера, но, что более важно, здесь нет скрытого O (n).

Strcat должен находить нулевой терминатор в каждой строке, которую он объединяет, и каждый раз проходить черезвесь буфер, чтобы найти конец.Каждый раз, когда строка становится длиннее, strcat замедляется.Спринтф, с другой стороны, может следить за концом.вы обнаружите, что

snprintf(buf, sizeof buf, "%s%s%s", "String1", "String2", "String3");

часто является более быстрым и более читаемым солютоном.

6 голосов
/ 02 августа 2011

То, как вы используете функцию strncat в своем коде кода, на самом деле будет подходящим для другой функции: strlcat (примечание l вместо n). Функция strlcat не является стандартной, но является популярной заменой strncat, предоставляемой реализацией. strlcat ожидает, что полный размер целевого буфера будет последним аргументом.

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

Я бы предложил, чтобы вместо того, чтобы ужасно злоупотреблять strncpy и делать явные повторные проверки с этими strlen вызовами (обе проблемы присутствуют в ответе Джо), вы либо используете предоставленный реализацией strlcat, либо реализуете его самостоятельно (если ваша реализация не предоставляет strlcat).

http://en.wikipedia.org/wiki/Strlcpy

3 голосов
/ 02 августа 2011

Это лучший способ сделать это. sizeof() просто дает вам размер указателя на данные, если вы не размещаете его локально (в этом случае вы сделали выделение локально, но лучше сделать это таким образом, и он будет работать, если код будет перераспределен).

#define MAXBUFFSIZE 64

char buff[MAXBUFFSIZE];

buff[0] = 0;  // or some string

strncat(buff, "String x",MAXBUFFSIZE - strlen(buff) - 1);
1 голос
/ 02 августа 2011

Хоган достаточно ответил на вопрос; однако, если вы беспокоитесь о переполнении буфера в strcat(...), вы должны также беспокоиться о переполнении буфера во всех других строковых функциях.

Используйте strnlen(...) и strncpy(...), чтобы действительно оставаться в буфере. Если у вас нет функции strnlen(...), напишите ее.

...