Отмена Microsoft SDL и memcpy

Как некоторые из вас могут знать, Microsoft запретила memcpy() из своего жизненного цикла разработки безопасности, заменив его на memcpy_s().

void *memcpy(void *dest, const void *src, size_t n);

/* simplified signature */
errno_t memcpy_s(void *dst, size_t dstsize, const void *src, size_t n);

Итак, если ваш код был:

if (in_len > dst_len) {
    /* error */
}
memcpy(dst, src, in_len);

он становится:

if (memcpy_s(dst, dst_len, src, src_len)) {
    /* error */
}

Или, с усечением,

memcpy(dst, src, min(in_len, dst_len));

против

(void)memcpy_s(dst, dst_len, src, src_len);

Вопрос: как дополнительный параметр длины делает код более безопасным? Чтобы использовать memcpy(), я должен уже знать все четыре параметра и передавать соответствующую длину в качестве третьего аргумента. Что мешает мне совершить ту же ошибку, просчитав размер буфера назначения и пропустив неправильный знак dst_size? Я не понимаю, почему он отличается от memcpy() и почему он устарел. Есть ли какой-либо общий вариант использования, который я не вижу? Что мне здесь не хватает?

Ответ 1

Ничто не мешает вам получить неверные параметры в "защищенной" версии. Microsoft, похоже, думает, что вы всегда будете использовать что-то вроде:

errno_t e = memcpy_s (&dstbuff, sizeof(dstbuff), &srcbuff, sizeof(srcbuff));

и проверьте ошибку.

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

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

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

Ответ 2

Дублирование информации всегда плохой дизайн - это просто дает вам больше шансов получить что-то неправильно. У Microsoft есть приложение appaling, когда дело доходит до разработки API, и были сохранены в прошлом только благодаря превосходству их документации. Утеплительно то, что они не могут удалить оригинальную функцию memcpy() - она ​​является частью ANSI C.

Ответ 3

Ты абсолютно прав. Если вы отслеживаете длину обоих буферов, memcpy безопасен в использовании. Если вы этого не сделаете, memcpy_s не сохранит вас.

Ответ 4

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

Если ничего другого, memcpy_s делает вас подумайте о размере цели буфер.

Ответ 5

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

Самое главное, memcpy_s возвращает код ошибки, указывающий, удалась ли вся копия, но с memcpy нет способа убедиться в этом. Это то, что Microsoft чувствует, делает memcpy_s более безопасным, чем memcpy.

Ответ 6

C подобная сборка предназначена для людей, которые знают, что они делают, я не забываю читать что-то вроде этого от K & R

Ответ 7

Я действительно иногда увольняюсь, действительно многие из нас, настоящие программисты, больше не видят в машине, что это такое, и любят смещать биты вокруг. Немного от темы, которую я знаю, но мне нравится точно знать, что происходит и определенно не хочет, чтобы какой-нибудь хромой сборщик мусора, обходящий фон, отчаянно пытаясь разобраться в неряшливых программистах грязных куч. Я имею в виду, насколько сложно сопоставлять вызовы free() с вызовами в malloc()/strdup(), насколько сложно удостовериться, что вы выделили достаточное пространство для буфера, чтобы знать, что вы можете вызвать memcpy() saefly? Ответ: Не очень, но 99,9% программистов действительно не заботятся о том, что они делают, потому что они просто на это за деньги, а не на страстность написания добросовестно секретной части кода.

End Rant.