Правильный способ использования `strcat ()`, когда дескриптору не хватает места? - PullRequest
0 голосов
/ 13 февраля 2019

man strcat говорит следующее.

char *strcat(char *restrict s1, const char *restrict s2);

В строке s1 должно быть достаточно места для хранения результата.

Какой правильный способ обработкиситуация, когда s1 не хватает места?

Ответы [ 3 ]

0 голосов
/ 13 февраля 2019

Программист обязан знать размер s1.Если вам не хватает места, вы можете вызвать realloc (s1, num_of_bytes), чтобы выделить больше места.

0 голосов
/ 13 февраля 2019

strcat(s1, s2); может привести к переполнению, поэтому мера предосторожности «В строке s1 должно быть достаточно места для хранения результата».

Предположим, что s1 может содержать N символов: N-1 не- '\0' + нулевой символ .

Правильный способ использования strcat(), когда в месте назначения недостаточно места?

Когда конкатенация может переполниться, я не вижу приложения для использования strcat(),Вместо этого используйте другие функции.


Для обнаружения потенциального переполнения:

  1. Проверка strlen(s1), strlen(s2) до вызова.

    size_t l1 = strlen(s1);
    assert(l1 < N); // This really should be true already.
    N -= l1;
    size_t l2 = strlen(s2);
    if (l1 >= N) Handle_TooBigSomehow();
    strcpy(s1 + l1, s2);
    
  2. Используйте strncat(char * restrict s1, const char * restrict s2, size_t n)

Обратите внимание, что n здесь , а не N: размер доступен для s1.

Функция strncat добавляет не более n символов (нулевой символ и символы, следующие за ним, не добавляются) из массива, на который указывает s2, до конца строки, на которую указываетs1.Начальный символ s2 заменяет нулевой символ в конце s1.Завершающий нулевой символ всегда добавляется к результату.C11 §7.23.3.2 2

    size_t l1 = strlen(s1);
    assert(l1 < N); // This really should be true already.
    strncat(s1, s2, N - 1 - l1);
    // or faster
    strncat(s1 + l1, s2, N - 1 - l1);

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

0 голосов
/ 13 февраля 2019

Если s1 не содержит достаточно места для хранения strlen(s1) + strlen(s2) + 1, попытка использовать strcat(s1, s2) имеет неопределенное поведение.

В strcat нет внутренней проверки переполнения буфера s1,Если вы переполнены, вы переполнены.Тем не менее, существуют некоторые специфичные для платформы альтернативы, которые при правильном использовании могут снизить риск переполнения.Как разработчик Windows, я предпочитаю StringCchCat и StringCbCat в <strsafe.h>.

Если вы хотите гарантировать безопасность для strcat, вы можете обернуть его самостоятельно.Что-то вроде:

int safe_strcat(char *s1, char *s2, size_t s1_size)
{
    if (strlen(s1) + strlen(s2) + 1 > s1_size)
    {
        return 0;
    }
    strcat(s1, s2);
    return 1;
}
...