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()
и почему он устарел.Есть ли какой-нибудь распространенный вариант использования, который я не вижу? Чего я здесь не понимаю?
Решение
Ничто не мешает вам также неправильно использовать параметры в "безопасной" версии.Microsoft, похоже, думает, что вы всегда будете использовать что-то вроде:
errno_t e = memcpy_s (&dstbuff, sizeof(dstbuff), &srcbuff, sizeof(srcbuff));
и проверьте ошибку.
Но это помогает только людям, которые не знают, что они делают с языком.На мой взгляд, эта группа людей либо не должна использовать этот язык, либо они должны научиться тому, как он работает должным образом.
Такого рода опора не принесет им никакой пользы в долгосрочной перспективе, поскольку их код не будет переносимым.
Теперь, возможно, Microsoft провела некоторый анализ и обнаружила, что было много проблем, вызванных неправильным использованием людьми memcpy()
и они думали, что это все исправит.Но, если бы это было так, я подозреваю, что лучшим решением было бы обучить разработчиков, а не заставлять их использовать нестандартные функции, которые будут недоступны в стандартных компиляторах.
Другие советы
Дублирование информации - это всегда плохой дизайн - это просто дает вам больше шансов сделать что-то неправильно.У Microsoft ужасающий послужной список, когда дело доходит до разработки API, и в прошлом ее спасало только превосходство их документации.Утешает то, что они не могут удалить исходную функцию memcpy() - это часть ANSI C.
Вы абсолютно правы.Если вы отслеживаете длины обоих буферов, memcpy безопасен в использовании.Если вы этого не сделаете, memcpy_s вас не спасет.
Вы ничего не упускаете, я думаю, что этот фрагмент из статьи, на которую вы ссылаетесь, в значительной степени охватывает это:
Как ничто другое, memcpy_s заставляет вас задуматься о размере целевого буфера.
По словам Microsoft, это немного упростит написание проверок качества кода - вы можете убедиться, что программист не передает одинаковое значение обоим параметрам size (что многие люди, вероятно, все равно сделали бы из-за лени).Другая вещь (на самом деле не связанная с безопасностью кода) заключается в том, что вы можете немного почистить свой код, используя этот метод, потому что в вашем коде меньше проверок - memcpy_s
функция проверит за вас, достаточно ли места в целевом буфере, исключив одну из ваших проверок.
Самый важный из всех, memcpy_s
возвращает код ошибки, указывающий, удалось ли выполнить всю копию, но с memcpy
нет никакого способа быть уверенным в этом. Это это то, что, по мнению Microsoft, делает memcpy_s
безопаснее , чем memcpy
.
C like assembly предназначен для людей, которые знают, что они делают, я помню, что читал что-то подобное непосредственно из K & R
Иногда я действительно сомневаюсь, что в мире действительно осталось не так много настоящих программистов, которые видят машину такой, какая она есть, и любят перекладывать биты.Я знаю, это немного не по теме, но мне нравится точно знать, что происходит, и я определенно не хочу, чтобы какой-нибудь отстойный сборщик мусора бродил на заднем плане, отчаянно пытаясь разобраться в беспорядочных кучах неаккуратных программистов.Я имею в виду, насколько сложно сопоставить вызовы free() с вызовами malloc() / strdup(), насколько сложно убедиться, что вы выделили достаточно места в буфере, чтобы знать, что вы можете вызывать memcpy() автоматически?Ответ:Не очень, но 99,9% программистов действительно не заботятся о том, что они делают, потому что они занимаются этим только ради денег, а не из страсти написать красиво оформленный фрагмент кода.
Конец разглагольствования.