Memcpy() в безопасном программировании?
Вопрос
Недавно я наткнулся на статья который утверждает, что Microsoft запрещает memcpy()
функционировать в своих безопасных магазинах программирования.Я понимаю уязвимости, присущие функции, но нужно ли запрещать ее использование полностью?
Следует ли избегать программ, которые я пишу memcpy()
полностью или просто обеспечить его безопасное использование?Какие существуют альтернативы, обеспечивающие аналогичную, но более безопасную функциональность?
Решение
Microsoft предоставляет альтернативы в memcpy и wmemcpy, которые проверяют их параметры.
memcpy_s говорит: «Хм, прежде чем я прочитаю этот адрес, позвольте мне убедиться, что это не нулевой указатель;и прежде чем я напишу по этому адресу, я проведу этот тест еще раз.Я также сравню количество байтов, которые меня попросили скопировать, с заявленным размером места назначения;если и только если вызов пройдет все эти тесты, я смогу выполнить копирование».
Memcpy говорит: «Задайте пункт назначения в регистр, заполняйте источник в регистр, заполните счет в регистр, выполните MOVSB или MOVSSW». (Пример на GeoCities, вскоре для этого мира: http://www.geocities.com/siliconvalley/park/3230/x86asm/asml1013.html)
Редактировать:Например, в дикой природе Ваше желание для меня закон подход к memcpy, рассмотрите OpenSolaris, где memcpy (для некоторых конфигураций) определено в терминах bcopy, и копирование (для некоторых конфигураций) - это...
void
33 bcopy(from, to, count)
34 #ifdef vax
35 unsigned char *from, *to;
36 int count;
37 {
38
39 asm(" movc3 12(ap),*4(ap),*8(ap)");
40 }
41 #else
42 #ifdef u3b /* movblkb only works with register args */
43 unsigned char *from, *to;
44 int count;
45 {
46 asm(" movblkb %r6, %r8, %r7");
47 }
48 #else
49 unsigned char *from, *to;
50 int count;
51 {
52 while ((count--) > 0)
53 *to++ = *from++;
54 }
55 #endif
Редактировать:Спасибо, Милли Смит!Вот что было на странице geocities, ссылку на которую я дал выше:
МОВС
Инструкция movs используется для копирования исходной строки в место назначения (да, копировать, а не перемещать).Данная инструкция имеет два варианта:мовсб и мовсв.movsb («перемещение байта строки») перемещает по одному байту за раз, тогда как movsw перемещает по два байта за раз.
Поскольку мы хотели бы переместить несколько байтов за раз, эти инструкции movs выполняются пакетами с использованием префикса Rep.Количество движений задается регистром CX.См. пример ниже:
:
lds si, [src]
les di, [dest]
cld
mov cx, 100
rep movsb
:
В этом примере скопируются 100 байтов из src в dest.Если вы замените movsb на movsw, вместо этого вы скопируете 200 байт.Если вы удалите префикс Rep, регистр CX не будет иметь никакого эффекта.Вы переместите один байт (если это movsb или 2 байта, если это movsw).
Другие советы
Бензопила при правильном использовании безопасна.То же самое и с memcpy().Но в обоих случаях, если вы ударитесь о гвоздь, он может отлететь и причинить вам боль.
Короче говоря, memcpy() необходим для низкоуровневых вычислений и никуда не денется, но для высокоуровневого программирования он вам не нужен.В Python нет memcpy().
Не беспокойтесь.Альтернативы Microsoft не намного лучше.Основная ценность заключается в том, что из-за этого ваш код становится непереносимым в Linux.Microsoft зарабатывает гораздо больше денег на ОС, которую они продают вашим клиентам, чем на купленной вами копии Visual C++.
В самой статье описывается более безопасная альтернатива:memcpy_s, который требует от вас указать максимальную длину цели.Когда это число предоставляется независимо от количества копируемых байтов, оно действует как барьер, предотвращающий переполнение буфера.Конечно, вы можете злоупотребить этим, назначив обоим одинаковый номер.
Запрет memcpy() в моем коде сделает меня лучшим программистом, а мое приложение безопаснее или просто сделает его более несовместимым?Я не уверен, действительно ли MS хочет что-то изменить или просто сделать новый код C несовместимым с другими компиляторами.Кстати.MS проделывает этот трюк со многими функциями, и это очень раздражает.strcpy -> strcpy_s -> StringCchCopy.
Я думаю, что C должен оставить программисту возможность прострелить себе ногу.Ручное управление памятью безопасно, если все сделано правильно.
Ты сам это сказал:«Microsoft запрещает функцию memcpy() в своем безопасные магазины программирования, я понимаю уязвимости, присущие функции,"
memcpy() и множество других стандартных функций, как известно, вызывают уязвимости, так почему же магазин безопасного программирования разрешает их использование, когда улучшение (пусть и постепенное) тривиально?
Несомненно, в своих усилиях по повышению безопасности собственных продуктов обзоры кода ясно показали, что эти функции ответственны за значительную часть уязвимостей, переполнений буфера и т. д.Вместо того, чтобы делать обертки только для внутреннего использования, они ввели их в стандартную библиотеку и добавили предупреждение компилятора (а не запрет) для всеобщего блага.
Если вы используете более старые версии, такие как C99 или C++98, или Solaris, вы не сможете использовать memcpy_s, если у вас не установлена библиотека Safe C.
memcpy_s() — это реализация, специфичная для Microsoft, которая не существует в реализациях, отличных от MS, включая ANSI, до C11, согласно их собственным стандартам.
Я оставлю в стороне все, что связано с РС и против РС, потому что это не имеет значения.
memmove() в любом случае является лучшим решением, поскольку оно решает проблему перекрытия.memmove_s() более надежен, но опять же, только если вы используете C11 или новее.
Альтернатива — позвонить memcpy_s
Вместо этого вы должны использовать memcpy_s().Такие же версии _s существуют для множества других функций, которые считаются небезопасными.