10

正如你们中的一些人可能知道的那样,微软禁止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()以及为什么它被弃用。有什么我看不到的常见用例吗?我在这里想念什么?

4

7 回答 7

14

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

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

并检查错误。

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

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

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

于 2009-05-18T07:26:52.730 回答
8

重复信息总是不好的设计——它只会给你更多出错的机会。微软在 API 设计方面有着令人震惊的记录,并且过去仅靠其卓越的文档才得以保存。令人欣慰的是,他们无法删除原始的 memcpy() 函数——它是 ANSI C 的一部分。

于 2009-05-18T08:27:13.047 回答
6

你完全正确。如果您要跟踪两个缓冲区的长度,则 memcpy 可以安全使用。如果你不是, memcpy_s 不会救你。

于 2009-05-18T07:34:31.253 回答
4

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

如果不出意外,memcpy_s 会让您考虑目标缓冲区的大小。

于 2009-05-18T07:25:17.023 回答
1

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

最重要的是,memcpy_s返回一个错误代码,指示整个复制是否成功,但memcpy没有办法确定这一点。 就是微软认为memcpy_smemcpy.

于 2009-05-18T07:38:10.903 回答
0

C like assembly is for people that know what they are doing, I remember to read something like that direcly from K&R

于 2009-10-25T16:53:48.760 回答
-1

有时我真的不以为然,世界上真正的程序员已经不多了,他们看到了机器的本来面目并喜欢四处移动。我知道有点离题,但我想确切地知道发生了什么,并且绝对不希望任何蹩脚的垃圾收集器在后台拼命地试图整理草率的程序员乱七八糟的堆。我的意思是,将 free() 的调用与 malloc()/strdup() 的调用相匹配有多难,确保分配足够的缓冲区空间以便知道可以安全地调用 memcpy() 有多难?回答:不是,但 99.9% 的程序员真的不在乎他们在做什么,因为他们只是为了钱,而不是为了写一段优美的代码。

结束咆哮。

于 2009-07-24T11:16:35.830 回答