Почему strncpy небезопасен?

Я ищу, чтобы узнать, почему strncpy считается небезопасным. Кто-нибудь имеет какую-либо документацию об этом или примеры использования эксплойта?

Ответ 1

Взгляните на этот сайт; это довольно подробное объяснение. В принципе, strncpy() не требует завершения NUL и поэтому подвержен множеству эксплойтов.

Ответ 2

Исходная проблема, очевидно, заключается в том, что strcpy (3) не был безопасная память, так что злоумышленник может предоставить строку длиннее, чем буфер, который будет перезаписывать код в стеке, и, если он будет тщательно организован, может выполнить произвольный код от злоумышленника.

Но strncpy (3) имеет другую проблему, поскольку в каждом случае в пункте назначения он не отправляет нулевое завершение. (Предположим, что длина источника больше, чем целевой буфер.) В будущих операциях может ожидаться соответствие строк с нулевым завершением между буферами одинакового размера и сбоями, расположенными ниже по потоку, когда результат копируется в третий буфер.

Использование strncpy (3) лучше, чем strcpy (3), но такие вещи, как strlcpy (3), еще лучше.

Ответ 3

Чтобы безопасно использовать strncpy, нужно либо (1) вручную вставить нулевой символ в буфер результатов, (2) знать, что буфер заканчивается нулем заблаговременно, а передать (длина-1) на strncpy или (3 ) знают, что буфер никогда не будет скопирован с использованием любого метода, который не свяжет его длину с длиной буфера.

Важно отметить, что strncpy будет заполнять нуль в буфере за скопированной строкой, в то время как другие варианты strcpy, ограниченные по длине, не будут. В некоторых случаях это может быть утечка производительности, но в других случаях это преимущество безопасности. Например, если вы использовали strlcpy для копирования "supercalifragilisticexpalidocious" в буфер, а затем для копирования "it", буфер будет содержать "it ^ ercalifragilisticexpalidocious ^" (используя "^" для представления нулевого байта). Если буфер скопирован в формат фиксированного размера, дополнительные данные могут маркироваться вместе с ним.

Ответ 4

Вопрос основан на "загруженной" предпосылке, которая делает этот вопрос недействительным.

Суть в том, что strncpy не считается небезопасным и никогда не считался небезопасным. Единственными претензиями на "неуверенность", которые могут быть связаны с этой функцией, являются широкие требования общей незащищенности модели памяти C и языка C. (Но это, очевидно, совершенно другая тема).

В рамках языка C ошибочное мнение о какой-то "неуверенности", присущей strncpy, вытекает из широко распространенного сомнительного шаблона использования strncpy для "безопасного копирования строк", то есть что-то, что эта функция не делает и никогда не предназначался для этого. Такое использование действительно сильно подвержено ошибкам. Но даже если вы ставите знак равенства между "склонностью к ошибкам" и "небезопасным", это все еще проблема использования (т.е. Проблема отсутствия образования), а не проблема strncpy.

В принципе, можно сказать, что единственная проблема с strncpy - это неудачное именование, которое заставляет программистов-новичков предположить, что они понимают, что делает эта функция вместо фактического чтения спецификации. Если посмотреть на имя функции, некомпетентный программист предполагает, что strncpy является "безопасной версией" strcpy, тогда как в действительности эти две функции полностью не связаны.

Точно такое же требование может быть сделано против оператора деления, например. Как известно большинству из вас, один из наиболее часто задаваемых вопросов о языке C выглядит следующим образом: "Я предположил, что 1/2 будет оцениваться до 0.5, но вместо этого я получил 0. Почему?" Тем не менее, мы не утверждаем, что оператор деления небезопасен только потому, что начинающие языки склонны неправильно истолковывать его поведение.

В другом примере мы не называем функции генерации псевдослучайных чисел "небезопасными" только потому, что некомпетентные программисты часто неприятно удивляются тем, что их вывод не является действительно случайным.

Именно так оно и есть с функцией strncpy. Так же, как требуется время для начинающих программистов, чтобы узнать, что на самом деле делают генераторы псевдослучайных чисел, требуется время, чтобы узнать, что на самом деле делает strncpy. Требуется время, чтобы узнать, что strncpy - это функция преобразования, предназначенная для преобразования строк с нулевым завершением в строки фиксированной ширины. Требуется время, чтобы узнать, что strncpy не имеет абсолютно никакого отношения к "безопасному копированию строк" ​​и не может быть осмысленно использован для этой цели.

Конечно, студенту-языку обычно требуется намного больше времени, чтобы узнать цель strncpy, чем разобраться с оператором деления. Однако это является основанием для любых претензий "отсутствия безопасности" в отношении strncpy.

P.S. Документ CERT, связанный в принятом ответе, посвящен именно тому, что: для демонстрации неуверенности типичного некомпетентного злоупотребления функцией strncpy как "безопасной" версии strcpy. Это никоим образом не означает, что сам strncpy как-то небезопасен.

Ответ 5

Путь Git 2.19 (Q3 2018) обнаруживает, что слишком сложно использовать функции API системы, такие как strcat(); strncpy() ;... и запрещает эти функции в этой кодовой базе.

См. Фиксацию e488b7a, фиксацию cc8fdae, фиксацию 1b11b64 (24 июля 2018 года) и совершение c8af66a (26 июля 2018 года) Джеффом Кингом (peff).
(Слияние с Юнио С Хамано - gitster - в совершении e28daf2, 15 августа 2018 года)

banned.h: mark strcat() как запрещен

Функция strcat() имеет все те же проблемы с переполнением, что и strcpy().
И в качестве бонуса легко оказаться случайно квадратичным, так как каждый последующий вызов должен пройти через существующую строку.

Последний strcat() ушел в f063d38 (демон: используйте cld-> env_array при повторном появлении, 2015-09-24, Git 2.7.0).
В общем случае, strcat() может быть заменен либо динамической строкой (strbuf или xstrfmt), либо xsnprintf если вы знаете, что длина ограничена.

Ответ 6

Худшая ситуация возникает, когда ваша буферная память источника и получателя перекрывается друг с другом. Поэтому избегайте использования strncpy, если вы чувствуете, что в вашей программе может возникнуть ситуация перекрытия. Вместо strncpy вы можете использовать функцию memmove в сценарии перекрытия.

Ниже я описываю простой пример, описывающий strncpy в перекрывающемся сценарии.

   #include <stdio.h>
   #include <string.h>
   int main() {

   char aszMessage[10] ="12345"; //Source Buffer
   short siLen=4; // Length of byte you want to copy


   strncpy(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap

   printf("\n\n\tMessage = %s\n",aszMessage);



   return 0;
}

Здесь я принимаю, выход должен быть 122345, но здесь выдается 122222, то есть самый большой резервный сценарий strncpy.

Эта проблема может быть решена с помощью функции memove.

 #include <stdio.h>
 #include <string.h>
 int main() {

 char aszMessage[10] ="12345"; //Source Buffer
 short siLen=4; // Length of byte you want to copy


 memmove(aszMessage + 2,aszMessage+1,siLen);//Here memory overlap

 printf("\n\n\tMessage = %s\n",aszMessage);


 return 0;
 }

Теперь я получаю выход 122345 желания.

Для более подробной информации вы можете увидеть эту ссылку http://aticleworld.com/how-to-use-strncpy-and-how-to-write-your-own-strncpy/

Ответ 7

Опасности strncpy, _snprintf и wcsncpy должны быть одинаково хорошо известны, но, по-видимому, это не так. Эти функции позволяют указать размер буфера, но - и это действительно важно - они не гарантируют нулевое завершение. Если вы попросите эти функции написать больше символов, чем заполнить буфер, то они остановятся - таким образом, избегая переполнения буфера, но они не будут завершать нуль буфера. Чтобы правильно использовать эти функции, вам нужно сделать такую ​​ерунду.

Пожалуйста, обратитесь к следующей ссылке для справки!!!

https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/