Отмена 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.