Microsoft SDL和memcpy弃用

正如你们中的一些人可能知道的那样, 微软从他们的安全开发生命周期中取消了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)); 

VS

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

问题:额外长度参数如何使代码更安全? 要使用memcpy() ,我应该已知所有四个参数,并将适当的长度作为第三个参数传递。 是什么阻止我犯错误计算目标缓冲区大小并传递错误的dst_size ? 我不明白为什么它与memcpy()什么不同以及为什么它被弃用了。 是否有任何我看不到的常见用例? 我在这里想念的是什么?

没有什么可以阻止你在“安全”版本中获取参数错误。 微软似乎认为你总会使用类似的东西:

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

并检查错误。

但这只能帮助那些不知道他们用语言做什么的人。 在我看来,这群人要么不应该使用这种语言,要么应该学习它是如何正常运作的。

从长远来看,这种拐杖不会对它们有任何好处,因为它们的代码不可移植。

现在可能是微软做了一些分析,发现人们滥用memcpy()导致了很多问题,他们认为这会解决问题。 但是,如果是这种情况,我怀疑更好的解决方案是教育开发人员而不是强迫他们使用标准编译器中不可用的非标准function。

信息重复总是糟糕的设计 – 它只会让你有更多的机会出错。 在API设计方面,微软拥有适当的记录,并且过去仅通过其优秀的文档保存。 令人欣慰的是,他们无法删除原始的memcpy()函数 – 它是ANSI C的一部分。

你是绝对正确的。 如果要跟踪缓冲区的长度,则可以安全地使用memcpy。 如果你不是,memcpy_s将不会救你。

你没有遗漏任何东西,我认为你链接的文章中的这个片段几乎涵盖了它:

如果没有别的,memcpy_s会让你考虑目标缓冲区的大小。

根据微软的说法,这将使编写代码质量检查变得容易一些 – 您可以检查以确保程序员不会将相同的值传递给两个大小参数(许多人可能仍然会因为懒惰而这样做)。 另一件事(实际上并不真正与代码安全性有关)是你可以使用这种方法稍微清理你的代码,因为代码中的检查要少 – memcpy_s函数会检查你是否有足够的空间目标缓冲区,消除了您的一个检查。

最重要的是, memcpy_s返回一个错误代码,指示整个副本是否成功,但是使用memcpy无法确定这一点。 就是微软认为memcpy_smemcpy更安全的原因。

对于那些知道自己在做什么的人来说,assembly就是这样,我记得从K&R那里直接读到这样的东西

我实际上有时候会发现,我们真的没有多少真正的程序员离开这个世界,他们更多地看到了机器的本来面目并喜欢转移一下。 我知道有点偏离主题,但我想确切地知道发生了什么,并且绝对不希望任何蹩脚的垃圾收集器在背景中肆无忌惮地试图理清那些邋mess的程序员凌乱的堆。 我的意思是,将调用free()与调用malloc()/ strdup()相匹配有多难,确保你已经分配了足够的缓冲区空间以便知道你可以调用memcpy()saefly有多难? 答:不是很好,但99.9%的程序员真的不在乎他们在做什么,因为他们只是为了钱,而不是写一个美妙的代码片段的热情。

结束咆哮。