18

我最近偶然发现了一篇文章,声称微软正在memcpy()其安全编程商店中禁止该功能。我了解该功能固有的漏洞,但有必要完全禁止使用它吗?

我编写的程序应该memcpy()完全避免,还是只是确保它被安全使用?有哪些替代品可以提供类似但更安全的功能?

4

10 回答 10

31

Microsoft 提供了 memcpy 和 wmemcpy 的替代方法来验证它们的参数。

memcpy_s 说,“嗯,在我从这个地址读取之前,让我自己验证它不是空指针;在我写入这个地址之前,我将再次执行该测试。我还将比较我的字节数已被要求复制到声称的目的地大小;当且仅当呼叫通过所有这些测试时,我才执行复制。”

memcpy 说“将目标填充到寄存器中,将源填充到寄存器中,将计数填充到寄存器中,执行 MOVSB 或 MOVSW。” (geocities 的例子,这个世界不久:http ://www.geocities.com/siliconvalley/park/3230/x86asm/asml1013.html )

编辑:对于 memcpy 的Your Wish Is My Command方法中的一个示例,请考虑 OpenSolaris,其中 memcpy (对于某些配置)是根据 bcopy 定义的,而bcopy(对于某些配置)是......

void
     33 bcopy(from, to, count)
     34 #ifdef vax
     35     unsigned char *from, *to;
     36     int count;
     37 {
     38 
     39     asm("   movc3   12(ap),*4(ap),*8(ap)");
     40 }
     41 #else
     42 #ifdef u3b      /* movblkb only works with register args */
     43     unsigned char *from, *to;
     44     int count;
     45 {
     46     asm("   movblkb %r6, %r8, %r7");
     47 }
     48 #else
     49     unsigned char *from, *to;
     50     int count;
     51 {
     52     while ((count--) > 0)
     53         *to++ = *from++;
     54 }
     55 #endif

编辑:谢谢,米莉史密斯!这是我在上面链接的 geocities 页面上的内容:

MOVS

指令 movs 用于将源字符串复制到目标中(是的,复制,而不是移动)。该指令有两种变体:movsb 和 movsw。movsb(“移动字符串字节”)一次移动一个字节,而 movsw 一次移动两个字节。

由于我们想一次移动几个字节,这些 movs 指令是使用 rep 前缀分批完成的。移动次数由 CX 寄存器指定。请参见下面的示例:

:
lds   si, [src]
les   di, [dest]
cld
mov   cx, 100
rep   movsb
:

此示例将从 src 复制 100 个字节到 dest。如果将 movsb 替换为 movsw,则改为复制 200 个字节。如果删除 rep 前缀,CX 寄存器将不起作用。您将移动一个字节(如果是 movsb,如果是 movsw,则移动 2 个字节)。

于 2009-05-15T17:57:27.383 回答
9

不要打扰。微软的替代品并没有那么好。主要价值在于这些会导致您的代码无法移植到 Linux。微软在他们卖给你客户的操作系统上赚的钱比他们在你购买的 Visual C++ 副本上赚的钱要多得多。

于 2009-10-15T12:14:48.780 回答
8

如果使用得当,电锯是安全的。与 memcpy() 相同。但在这两种情况下,如果你撞到钉子,它就会飞起来伤害你。

简而言之,低级计算需要 memcpy() 并且不会消失,但对于高级编程,您不需要它。Python 中没有 memcpy() 。

于 2009-05-15T17:54:58.713 回答
6

文章本身描述了一个更安全的替代方案:memcpy_s,它要求您指定目标的最大长度。当该数字独立于要复制的字节量提供时,它可以作为防止缓冲区溢出的屏障。当然,您可以通过给两者提供相同的号码来滥用它。

于 2009-05-15T17:55:37.497 回答
3

在我的代码中禁止 memcpy() 是让我成为更好的程序员和我的应用程序更安全还是更不兼容?我不确定,如果 MS 真的想改变任何东西,或者只是让任何新的 C 代码与其他编译器不兼容。顺便提一句。MS 在许多功能上都使用了这个技巧,这很烦人。strcpy -> strcpy_s -> StringCchCopy。

于 2009-06-14T15:47:32.360 回答
2

我认为 C 应该留给程序员一个选择自己的脚。如果操作正确,手动内存管理是安全的。

于 2009-05-15T18:42:56.320 回答
2

你自己说过:“微软在其安全编程商店中禁止使用 memcpy() 函数,我理解该函数固有的漏洞,”

众所周知,memcpy() 和许多其他标准函数会导致漏洞,那么当(尽管是增量的)改进微不足道时,为什么安全的编程商店会允许使用它们呢?

毫无疑问,在他们努力提高自己产品的安全性的过程中,代码审查清楚地表明,这些函数是造成很大一部分漏洞、缓冲区溢出等的原因。他们没有制作包装器供内部使用,而是将它们引入标准库并为了所有人的利益添加了编译器警告(不是禁令)。

于 2009-10-15T12:05:19.797 回答
-1

另一种方法是调用memcpy_s

于 2009-05-15T17:55:53.797 回答
-1

如果您使用的是旧版本,例如 C99 或 C++98,或者在 Solaris 上,则不能使用 memcpy_s,除非您安装了 Safe C 库。

memcpy_s() 是 Microsoft 特定的实现,根据他们自己的标准,在 C11 之前的非 MS 实现(包括 ANSI)上不存在。

我将把支持 MS 和反 MS 的东西放在一边,因为这无关紧要。

memmove() 无论如何都是一个更好的解决方案,因为它解决了重叠问题。memmove_s() 更健壮,但同样,仅当您使用 C11 或更高版本时。

于 2017-05-11T22:45:46.603 回答
-2

您应该改用 memcpy_s() 。对于被认为是不安全的各种其他功能,存在相同类型的 _s 版本。

于 2009-05-15T17:56:16.183 回答