Почему strlcpy и strlcat считают небезопасными?

Я понимаю это strlcpy и strlcat были разработаны как безопасные замены для strncpy и strncat. Однако некоторые люди все еще имеют мнение, что они небезопасны, и просто вызывают другой тип проблемы.

Может кто-то давать пример как использование strlcpy или strlcat (т.е. функция, что всегда пустой указатель завершает свои строки) может привести к проблемам безопасности?

Ulrich Drepper и James Antill заявляют, что это верно, но никогда не обеспечивайте примеры или проясняйте эту мысль.

77
задан Palec 31 May 2017 в 10:03
поделиться

5 ответов

Критика Ульриха основана на идее, что усечение строки, которая не обнаруживается программой, может привести к вопросам безопасности, через неверную логику. Поэтому быть безопасным, вам нужно проверить на усечение. Для этого для соединения строки означает, что вы выполняете проверку по строкам этого:

if (destlen + sourcelen > dest_maxlen)
{
    /* Bug out */
}

Теперь Strlcat эффективно делает эту проверку, если программист вспоминает, чтобы проверить результат - так что вы Можно Использовать его безопасно:

if (strlcat(dest, source, dest_bufferlen) >= dest_bufferlen)
{
    /* Bug out */
}

Точка Ульриха заключается в том, что поскольку вы должны иметь Destlen и SourceLen (или пересчитывают их, что это то, что strlcat Эффективно делает), вы также можете просто использовать более эффективную memcpy в любом случае:

if (destlen + sourcelen > dest_maxlen)
{
    goto error_out;
}
memcpy(dest + destlen, source, sourcelen + 1);
destlen += sourcelen;

(в вышеуказанном коде, DEST_MAXLEN - максимальная длина строки, которая может Хранится в DEST - один меньше, чем размер буфера . DEST_BUFFERLEN - полный размер Buffer ).

31
ответ дан 24 November 2019 в 10:51
поделиться

Когда люди говорят: « strcpy () опасно, используйте strncpy () вместо« (или аналогичных утверждений о strcat () и т. Д., Но Я собираюсь использовать strcpy () здесь, как мой фокус), они означают, что нет никаких границ, проверку в strcpy () . Таким образом, чрезмерно длительная строка приведет к перераспонаванию буфера. Они верны. Использование strncpy () В этом случае предотвратит перерасход буфера.

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

Как программист C, вы должны знать размер назначения, прежде чем пытаться скопировать строки. Это предположение в strncpy () и STRLCPY () последних параметров тоже: вы поставляете этот размер к ним. Вы также можете знать размер источника до скопирования строк. Затем, если пункт назначения недостаточно велик, не звонит strcpy () . Либо перераспределите буфер или сделайте что-нибудь еще.

Почему я не люблю strncpy () ?

  • strncpy () - это плохое решение в большинстве случаев: ваша строка будет усечена без каких-либо уведомлений - я бы предпочел написать Дополнительный код, чтобы понять это, а затем пройти курс действий, которые я хочу взять, а не позволить некоторую функцию решить для меня о том, что делать.
  • strncpy () очень неэффективно. Он пишет на каждый байт в буфере назначения. Вам не нужны эти тысячи '\ 0' в конце вашего пункта назначения.
  • Это не пишет завершение '\ 0' , если пункт назначения недостаточно велик. Итак, вы должны сделать это самостоятельно. Сложность этого не стоит.

Теперь мы приходим к Strlcpy () . Изменения из strncpy () делают его лучше, но я не уверен, если удельное поведение strl * гарантирует свое существование: они слишком специфики. Вы все еще должны знать размер назначения. Это более эффективно, чем strncpy () , потому что он не обязательно пишет каждому байту в месте назначения. Но это решает проблему, которая может быть решена путем выполнения: * (((CHAR *) Mempcpy (DST, SRC, N)) = 0; .

Я не думаю, что кто-то говорит, что strlcpy () или STRLCAT () может привести к проблемам безопасности, что они (и я) говорят, что они могут привести к ошибкам Например, когда вы ожидаете, что полная строка будет написана вместо его части.

Основная проблема здесь: Сколько байтов копировать? Программист должен знать это, и если он не, strncpy () или STRLCPY () не спасет его.

STRLCPY () и STRLCAT () не являются стандартными, ни ISO C, ни POSIX. Таким образом, их использование в портативных программах невозможно. Фактически, strlcat () имеет два разных варианта: Реализация Solaris отличается от других для краевых чехлов, включающих длину 0. Это делает его еще менее полезным, чем иным образом.

19
ответ дан 24 November 2019 в 10:51
поделиться

Я думаю, что Ульрич и другие думают, что это даст ложное чувство безопасности. Случайно усеченные строки могут имеют последствия безопасности для других частей кода (например, если файловая система усекается, программа может не выполнять операции по предполагаемому файлу).

12
ответ дан 24 November 2019 в 10:51
поделиться

Существует два «проблема», связанных с использованием функций STRL:

  1. , вы должны проверить возвратные значения Чтобы избежать усечения.

Стандартные черновые писатели C1x и Drepper утверждают, что программисты не проверят возвращаемое значение. DREPPER говорит, что мы должны как-то знать длину и использовать memcpy, и избегайте функций строки, в целом в соответствии со строковыми функциями утверждают, что безопасная strcpy должна возвращать ненулевой на усечение, если иное не указано флаг _truncate . Идея состоит в том, что люди, скорее всего, используют, если (strncpy_s (...)).

  1. нельзя использовать на некруточных строках.

Некоторые люди считают, что строковые функции никогда не должны сбояться даже при кормите божественные данные. Это влияет на стандартные функции, такие как strlen, которые в нормальных условиях будут SegFault.Новый стандарт будет включать в себя много таких функций. Проверки курса имеют штраф производительности.

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

7
ответ дан 24 November 2019 в 10:51
поделиться

Во-первых, STRLCPY никогда не предназначался в качестве безопасной версии strncpy strncpy , никогда не был предназначен как Безопасная версия strcpy ). Эти две функции полностью не связаны. strncpy - это функция, которая не имеет отношения к строкам C-Strings (I.e. NULL-LECLING) вообще. Тот факт, что он имеет префикс ... префикс в его названии, является просто исторической ошибкой. История и цель strncpy является известным и хорошо документированным. Это функция, созданная для работы с так называемыми строками «фиксированной ширины» (не с C-Strings), используемых в некоторых исторических версиях файловой системы UNIX. Некоторые программисты сегодня запутаются по своему названию и предполагают, что strncpy как-то должен служить функцией копирования C-строки с ограниченным длиной («безопасный» STRCPY strcpy ), который в Реальность является полной ерундой и приводит к плохому программированию практики. C Стандартная библиотека в своей текущей форме не имеет функции для копирования C-String C-String Limited-длины. Это где STRLCPY вписывается . STRLCPY действительно является настоящей функцией копирования длиной, созданной для работы с C-Strings. STRLCPY правильно делает все функцию копирования на ограниченную длину. Единственная критика, которую можно нацелиться на то, что она состоит в том, что она сожалеет, а не стандартная.

Во-вторых, strncat , с другой стороны , на самом деле, действительно работает функция, которая работает с C-Strings, и выполняет конкатенацию ограниченного длины (это действительно «безопасный» брат Strcat ). Чтобы правильно использовать эту функцию, программист должен взять на себя особую медицинскую помощь, поскольку параметр размера Эта функция принимает, на самом деле не является размером буфера, который получает результат, а скорее размер его оставшейся части (также символ терминатора подсчитывается неявно). Это может быть запутано, поскольку для того, чтобы привязать этот размер до размера буфера, программист должен не забывать выполнять некоторые дополнительные расчеты, которые часто используются для критики STRCAT . Strlcat заботится об этих проблемах, изменяя интерфейс, так что никакие дополнительные расчеты не нужны (по крайней мере, в коде вызова). Опять же, единственная основа, которую я вижу, можно критиковать это, это то, что функция не является стандартной. Кроме того, функции из STRCAT группы - это то, что вы не увидите в профессиональном коде очень часто из-за ограниченного использования самой идеи конкатенации строк на основе сканирования.

Что касается того, как эти функции могут привести к проблемам безопасности ... они просто не могут. Они не могут привести к проблемам безопасности в какой-либо большей степени, чем сам язык C может «привести к проблемам безопасности». Вы видите, что в течение некоторого времени появилось сильное настроение там, что язык C ++ должен двигаться в направлении развития в какой-то странный аромат Java.Это чувство иногда разливается в домен языка C, что приведет к довольно невежественной и принудительной критике языковых особенностей C и особенности стандартной библиотеки. Я подозреваю, что мы можем иметь дело с чем-то подобным в этом случае, хотя я надеюсь, что все на самом деле не так плохо.

106
ответ дан 24 November 2019 в 10:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: