【问题标题】:How to set number of bytes with memcpy?如何使用 memcpy 设置字节数?
【发布时间】:2014-04-12 15:23:33
【问题描述】:

我读到了 heartbleed 漏洞,这是 memcpy 的错误。

void * memcpy( void * dest, const void *src, size_t len );

对 memcpy 的正确调用可能如下所示

int a[4711] [4711];
 int b[4711] [4711];
/* initialize a */
(void) memcpy( &b [0] [0], &a [0] [0], sizeof( a ) );

但是为什么第三个参数,什么时候会和src的大小不同呢?我看过其他示例,其中使用的是 dest 大小,应该什么时候完成?

【问题讨论】:

  • 我想你的意思是memcpy 不是memcopy
  • 嗯,memcpy 的用例比创建两个结构的精确副本要广泛得多,也复杂得多。假设你只需要复制a的一部分。
  • 另外,C 无法查看调用函数的源代码来猜测您实际想要复制哪个数组以及其中的多少。
  • 为什么投反对票?这是一个历史悠久的重要问题,特别是对于那些使用 Java 或其他内存管理语言进行编程的人。

标签: c memcpy heartbleed-bug


【解决方案1】:

如果您查看memcpyMan 页面,第三个参数是从 src 复制到 dst 的字节数。所以使用 src 的大小或 dst 的大小都没有关系。但是您必须确保源缓冲区和目标缓冲区的大小至少等于或大于复制的字节数。否则会发生缓冲区溢出。

【讨论】:

    【解决方案2】:

    memcpy(dst,src,len) 的第三个参数给出了要复制的字节数。

    如果该字节数大于任一参数所指向的内存,您就上当了。这是一个描述诸如 Heartbleed bug 之类的技术术语,以及我的许多其他 bug有过愉快的经历 :-( 修复。

    如果您的软件开发思维方式面向内存对象,那么您问题中的代码模式是有效的。例如,如果您围绕使用memcpy() 来制作整个对象的精确副本的想法进行开发,我想您将永远不会使用除sizeof(src) 之外的任何第三个参数。

    memcpy() 对于许多其他类型的操作很有用,例如管理部分缓冲区、将不连贯的数据流收集到连续的内存位置以及类似的事情。

    它也容易被滥用,并且通常不会对此进行检查。例如,在野外可能有数以万计的代码 sn-ps,其中许多在嵌入式系统中,看起来像这样。

    char [10] out;
    char [] in = "Yo ho ho and a bottle of rum!";
    ...
    memcpy (out, in, 1+ strlen(in));  /*don't do this or you're hosed!*/
    

    【讨论】:

    • 另一个常见的例子使用:计数字符串。
    • 只是一个C提醒:上面的代码应该是char out[10]; char in[];
    【解决方案3】:

    在这种情况下,srcdest 数组的大小相同,因此您在 sizeof 上执行哪一个并不重要。

    一般来说,如果您使用dest 大小,那么您可以保证您的写入不会导致缓冲区溢出,这通常(但不总是)比阅读超过src 的结尾更严重。

    但是,阅读超过 src 的结尾也可能很严重,如 Heartbeat 案例所示。为了保持稳健,最好在继续之前检查 srcdest 的大小并确认它们都符合您的预期。

    【讨论】:

    • 不同大小的缓冲区有很多用例,截断一处很容易导致其他地方溢出。此外,阅读过多会导致各种不好的事情发生,这取决于上下文。
    猜你喜欢
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    相关资源
    最近更新 更多