【发布时间】:2010-10-26 13:58:25
【问题描述】:
我最近偶然发现an article 声称微软正在其安全编程商店中禁止memcpy() 功能。我了解该功能固有的漏洞,但是否有必要完全禁止其使用?
我编写的程序应该完全避免memcpy(),还是只是确保它被安全使用?有哪些替代品可以提供类似但更安全的功能?
【问题讨论】:
我最近偶然发现an article 声称微软正在其安全编程商店中禁止memcpy() 功能。我了解该功能固有的漏洞,但是否有必要完全禁止其使用?
我编写的程序应该完全避免memcpy(),还是只是确保它被安全使用?有哪些替代品可以提供类似但更安全的功能?
【问题讨论】:
如果使用得当,电锯是安全的。与 memcpy() 相同。但在这两种情况下,如果你碰到钉子,它就会飞起来伤害你。
简而言之,memcpy() 是低级计算所必需的并且不会消失,但对于高级编程则不需要它。 Python 中没有 memcpy()。
【讨论】:
文章本身描述了一个更安全的替代方案:memcpy_s,它要求你指定目标的最大长度。当该数字独立于要复制的字节数提供时,它可以作为防止缓冲区溢出的屏障。当然,您可以通过给两者提供相同的号码来滥用它。
【讨论】:
memcpy(dest, src, MIN(destsize,count))。但是我看不出这有什么用处。 MS 刚刚起步。
另一种方法是致电memcpy_s
【讨论】:
memcpy_s 是非标准且特定于供应商的
你应该使用 memcpy_s() 代替。对于被认为是不安全的各种其他功能,存在相同类型的 _s 版本。
【讨论】:
memcpy_s 是非标准且特定于供应商的
Microsoft 向 memcpy 和 wmemcpy 提供 alternatives 以验证其参数。
memcpy_s 说:“嗯,在我从这个地址读取之前,让我自己验证它不是空指针;在我写入这个地址之前,我将再次执行该测试。我还将比较数字我被要求将字节数复制到声明的目标大小;当且仅当调用通过所有这些测试时,我才执行复制。”
memcpy 说“将目标填充到寄存器中,将源填充到寄存器中,将计数填充到寄存器中,执行 MOVSB 或 MOVSW。” (geocities 的例子,这个世界不久:http://www.geocities.com/siliconvalley/park/3230/x86asm/asml1013.html)
编辑:对于 memcpy 的 Your Wish Is My Command 方法中的一个示例,请考虑 OpenSolaris,其中 memcpy 是(对于某些配置)defined in terms of 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 用于将源字符串复制到目标中(是的,复制,而不是移动)。该指令有两种变体: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 个字节)。
【讨论】:
我认为 C 应该给程序员留下一个选择,让程序员自己动手。 如果操作正确,手动内存管理是安全的。
【讨论】:
在我的代码中禁止 memcpy() 是否会使我成为更好的程序员和我的应用程序更安全还是更不兼容?我不确定,如果 MS 真的想改变任何东西,或者只是让任何新的 C 代码与其他编译器不兼容。顺便提一句。 MS在许多功能上都使用了这个技巧,这很烦人。 strcpy -> strcpy_s -> StringCchCopy.
【讨论】:
您自己说过:“微软在其安全编程商店中禁止使用 memcpy() 函数,我了解函数固有的漏洞,”
memcpy() 和许多其他标准函数已知会导致漏洞,那么当(尽管是增量的)改进微不足道时,为什么安全的编程商店会允许使用它们呢?
毫无疑问,在他们努力提高自己产品的安全性的过程中,代码审查清楚地表明,这些功能是造成很大一部分漏洞、缓冲区溢出等的原因。他们没有制作包装器供内部使用,而是将它们引入为了所有人的利益,标准库并添加了编译器警告(不是禁令)。
【讨论】:
security 不是真正的解决方案。在这方面还有其他尝试,例如)OpenBSD strlcpy 和 strlcat,由于类似的原因被拒绝。
不要打扰。微软的替代品并没有那么好。主要价值在于这些会导致您的代码无法移植到 Linux。 Microsoft 在向您的客户销售的操作系统上赚的钱比在您购买的 Visual C++ 副本上赚的钱要多。
【讨论】:
如果您使用的是旧版本,例如 C99 或 C++98,或者在 Solaris 上,则不能使用 memcpy_s,除非您安装了 Safe C 库。
memcpy_s() 是 Microsoft 特定的实现,根据他们自己的标准,在 C11 之前的非 MS 实现(包括 ANSI)上不存在。
我会把赞成 MS 和反对 MS 的东西放在一边,因为这无关紧要。
memmove() 无论如何是一个更好的解决方案,因为它解决了重叠问题。 memmove_s() 更健壮,但同样,仅当您使用 C11 或更高版本时。
【讨论】: