正如你们中的一些人所知,Microsoft banned memcpy()
from their Security Development Lifecycle,将其替换为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));
VS
(void)memcpy_s(dst, dst_len, src, src_len);
问题:额外长度参数如何使代码更安全?要使用memcpy()
,我应该已知所有四个参数,并将适当的长度作为第三个参数传递。是什么阻止我犯错误计算目标缓冲区大小并传递错误的dst_size
值?我不明白为什么它与memcpy()
有任何不同以及它被弃用的原因。有没有我看不到的常见用例? 我在这里缺少什么?
答案 0 :(得分:14)
没有什么可以阻止你在“安全”版本中获取参数错误。微软似乎认为你总会使用类似的东西:
errno_t e = memcpy_s (&dstbuff, sizeof(dstbuff), &srcbuff, sizeof(srcbuff));
并检查错误。
但这只能帮助那些不知道他们在用语言做什么的人。在我看来,这群人要么不应该使用这种语言,要么应该了解它是如何正常运作的。
从长远来看,这种拐杖不会对它们产生任何好处,因为它们的代码不可移植。
现在可能是微软做了一些分析,发现人们滥用memcpy()
引起了很多问题,他们认为这会解决问题。但是,如果是这种情况,我怀疑更好的解决方案是教育开发人员而不是强迫他们使用标准编译器中不可用的非标准功能。
答案 1 :(得分:8)
重复信息总是糟糕的设计 - 它只会让你有更多的机会出错。在API设计方面,微软拥有适当的记录,并且过去仅通过其优秀的文档保存。令人欣慰的是,它们无法删除原始的memcpy()函数 - 它是ANSI C的一部分。
答案 2 :(得分:6)
你是完全正确的。如果要跟踪两个缓冲区的长度,memcpy可以安全使用。如果你不是,memcpy_s将不会救你。
答案 3 :(得分:4)
你没有遗漏任何东西,我认为你链接的文章中的这个片段几乎涵盖了它:
如果没有别的,memcpy_s会让你 想一想目标的大小 缓冲液中。
答案 4 :(得分:1)
根据微软的说法,这将使编写代码质量检查变得容易一些 - 您可以检查以确保程序员不会将相同的值传递给两个大小参数(许多人可能仍然会这样做)懒惰)。另一件事(实际上并不真正与代码安全性有关)是你可以使用这种方法稍微清理你的代码,因为代码中的检查要少 - memcpy_s
函数会检查你那里在目标缓冲区中有足够的空间,从而消除了一个检查。
最重要的是,memcpy_s
返回一个错误代码,指示整个副本是否成功,但是memcpy
无法确定这一点。 此是Microsoft认为memcpy_s
比memcpy
更安全的原因。
答案 5 :(得分:0)
答案 6 :(得分:-1)
我实际上有时会发现,我们真的没有多少真正的程序员离开这个世界,他们更多地看到机器的本来面目并喜欢转移。我知道有点偏离主题,但我想确切地知道发生了什么,并且绝对不希望任何蹩脚的垃圾收集器在背景中肆无忌惮地试图理清邋mess的程序员凌乱的堆。我的意思是,将调用free()与调用malloc()/ strdup()相匹配有多难,确保你已经分配了足够的缓冲区以便知道你可以调用memcpy()saefly有多难?答:不是很好,但99.9%的程序员真的不在乎他们在做什么,因为他们只是为了钱,而不是写一个美妙的代码片段的热情。
结束Rant。