0

我知道有很多关于 memcpy() 在 Windows/Microsoft 世界中如何不安全的讨论,但这是否也适用于 Mac OS X 代码(Cocoa)?如果是这样,在 Cocoa 中应该使用什么函数来获得最大的安全性?memcpy_s() 似乎不存在于平台上。

谢谢。

更新:我意识到即使在 Windows 中谈论 memcpy() 也是一个灰色区域(请参阅安全编程中的 Memcpy()?),但我试图发现同样的确切讨论是否适用于 Mac OS X。Mac OS X 不包含 memcpy() 的“安全”版本这一事实似乎暗示 Apple 认为事情并没有那么糟糕。

4

4 回答 4

3

当内存区域可以重叠时,您应该使用memmove而不是memcpy 。

如果您进行防御性编程并且知道它们实际在做什么,它们本质上并不是不安全的。

于 2012-04-16T12:59:31.390 回答
2

这是相当新的 AFAIK,并不完美,但 GCC 提供了一个名为的包装器__memcpy_chk,它在可能的情况下检查目标的大小,看看这里。它的用法(来自同一资源):

 #undef memcpy
 #define bos0(dest) __builtin_object_size (dest, 0)
 #define memcpy(dest, src, n) \
   __builtin___memcpy_chk (dest, src, n, bos0 (dest))

 char *volatile p;
 char buf[10];
 /* It is unknown what object p points to, so this is optimized
    into plain memcpy - no checking is possible.  */
 memcpy (p, "abcde", n);
 /* Destination is known and length too.  It is known at compile
    time there will be no overflow.  */
 memcpy (&buf[5], "abcde", 5);
 /* Destination is known, but the length is not known at compile time.
    This will result in __memcpy_chk call that can check for overflow
    at runtime.  */
 memcpy (&buf[5], "abcde", n);
 /* Destination is known and it is known at compile time there will
    be overflow.  There will be a warning and __memcpy_chk call that
    will abort the program at runtime.  */
 memcpy (&buf[6], "abcde", 5);
于 2012-04-16T12:53:48.463 回答
2

缓冲区溢出(这是 memcpy、strcpy 等人的安全问题)与操作系统无关;本质上,它们是 C 语言固有的问题,因为它不提供自动边界检查。

谨慎使用,memcpy 是安全的;例如,如果您自己验证参数,或者在编译时知道大小。但是每个人都会犯错。

MS 禁止 memcpy 和使用自己的 memcpy_s 的方法是通过强制程序员在任何地方进行额外的安全检查来减少错误。如果需要,您可以编写自己的 memcpy_s;这并不难,只需实现其 MSDN 页面上描述的行为即可。

...似乎暗示 Apple 认为事情并没有那么糟糕。

推论是微软觉得事情很糟糕。但是,公司对问题的看法并不影响所述问题的存在,即不验证您对 memcpy 的输入会导致一类漏洞。

于 2012-04-16T13:01:34.193 回答
1

我对微软的印象不深,memcpy_s()因为它仍然取决于调用者来提供目标缓冲区大小。由于可能出错的主要问题memcpy()(源缓冲区和目标缓冲区重叠除外)是由于不知道目标缓冲区的实际大小引起的,所以调用者不太可能将错误的目标大小放入其中吗?

我想有一类错误可以帮助解决,例如:

  char anArray[10]
  char* foo = anArray;
  memcpy_s(foo, sizeof foo, somewhereElse, 10);
  // or
  memcpy_s(foo, sizeof *foo, somewhereElse, 10);

然而,这两者都表明了对 C 指针的根本误解,并且可能不是代码的唯一问题。

如果目的地太小,你会怎么做?您是否继续处理截断的数据?您是否发出一条错误消息说“警告:程序员是个白痴”?不,最好在开始复制之前知道您的目标缓冲区足够大。

此外,问题中的链接谈到memcpy_s()了空指针检查。再说一次,你要做什么?让程序崩溃几乎是您可以做的一切,因为如果您希望不为 null 的指针为 null,则您不能信任程序运行环境的任何部分。在现代 PC 操作系统上,一旦memcpy()尝试取消引用空指针,程序就会崩溃。

于 2012-04-16T14:23:02.537 回答