Memcpy () в безопасном программировании? - PullRequest
15 голосов
/ 15 мая 2009

Недавно я наткнулся на статью , в которой утверждается, что Microsoft запрещает функцию memcpy() в своих магазинах безопасного программирования. Я понимаю уязвимости, присущие функции, но необходимо ли полностью запретить ее использование?

Должны ли программы, которые я пишу, избегать memcpy() целиком или просто обеспечивать их безопасное использование? Какие существуют альтернативы, обеспечивающие аналогичную, но более безопасную функциональность?

Ответы [ 10 ]

29 голосов
/ 15 мая 2009

Microsoft предоставляет альтернативы для memcpy и wmemcpy, которые проверяют их параметры.

memcpy_s говорит: «Хм, прежде чем я прочитаю с этого адреса, позвольте мне убедиться, что это не нулевой указатель; и прежде чем писать по этому адресу, я снова выполню этот тест. Я также сравню число из байтов, которые мне было предложено скопировать в заявленный размер места назначения; если и только если вызов пройдет все эти тесты, я выполню копию. "

memcpy говорит: «Запишите получателя в регистр, запишите источник в регистр, запишите счет в регистр, выполните MOVSB ​​или MOVSW». (Пример для геогородов, недолгих для этого мира: http://www.geocities.com/siliconvalley/park/3230/x86asm/asml1013.html)

Edit: для примера в дикой природе Ваш запрос - моя команда подход к memcpy, рассмотрим OpenSolaris, где memcpy (для некоторых конфигураций) , определенный в терминах bcopy и 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

Редактировать: Спасибо, Милли Смит! Вот то, что было на странице геокоссий, на которую я ссылался выше:

MOVS

Инструкция movs используется для копирования исходной строки в место назначения (да, копировать, а не перемещать). Эта инструкция имеет два варианта: movsb и movsw. Movsb («Move string byte») перемещает один байт за раз, тогда как 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).

8 голосов
/ 15 октября 2009

Не беспокойся. Альтернативы Microsoft не намного лучше. Основная ценность заключается в том, что это приводит к тому, что ваш код становится непереносимым в Linux. Microsoft зарабатывает гораздо больше денег на ОС, которую они продают вашим клиентам, чем на копии купленной вами Visual C ++.

8 голосов
/ 15 мая 2009

Бензопила, при правильном использовании, безопасна. То же самое с memcpy (). Но в обоих случаях, если вы ударите по гвоздю, он может летать и причинять вам боль.

Короче говоря, memcpy () требуется для низкоуровневых вычислений и не исчезнет, ​​но для высокоуровневого программирования вам это не нужно. В Python нет memcpy ().

6 голосов
/ 15 мая 2009

В самой статье описана более безопасная альтернатива: memcpy_s, которая требует от вас указать максимальную длину цели. Когда это число предоставляется независимо от количества байтов для копирования, оно действует как барьер для предотвращения переполнения буфера. Конечно, вы можете злоупотребить этим, дав одинаковое число обоим.

3 голосов
/ 14 июня 2009

Позволяет ли запрет на использование memcpy () в моем коде сделать меня лучшим программистом, а мое приложение более безопасным или просто более несовместимым? Я не уверен, действительно ли MS хочет что-то изменить или просто сделать любой новый код на C несовместимым с другими компиляторами. Btw. MS делает этот трюк на многих функциях, и это довольно раздражает. strcpy -> strcpy_s -> StringCchCopy.

2 голосов
/ 15 октября 2009

Вы сами сказали: «Microsoft запрещает функцию memcpy () в своих магазинах безопасного программирования , я понимаю уязвимости, присущие функции

memcpy () и множество других стандартных функций, как известно, вызывают уязвимости, так почему бы безопасный магазин программирования разрешить их использование, когда (хотя и постепенное) улучшение является тривиальным?

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

2 голосов
/ 15 мая 2009

Я думаю, что С должен оставить возможность программисту стрелять собственной ногой ручное управление памятью безопасно, если все сделано правильно.

0 голосов
/ 12 мая 2017

Если вы используете более старые версии, такие как C99 или C ++ 98, или в Solaris, вы не можете использовать memcpy_s, если у вас не установлена ​​библиотека Safe C.

memcpy_s () - это специфическая для Microsoft реализация, которой нет в реализациях не от MS, включая ANSI, до C11, согласно их собственным стандартам.

Я оставлю про-MS и анти-MS вещи в стороне, потому что это не имеет значения.

memmove () в любом случае является лучшим решением, поскольку оно решает проблему наложения. memmove_s () более устойчив, но опять же, только если вы находитесь в C11 или позже.

0 голосов
/ 15 мая 2009

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

0 голосов
/ 15 мая 2009

Альтернативой является вызов memcpy_s

...