我读到了关于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的大小不同?我已经看过其他例子,它们使用的是目标大小,应该何时完成?
答案 0 :(得分:4)
如果查看memcpy
Man页面,第三个参数是从src复制到dst的字节数。因此,如果使用src的大小或dst的大小,这并不重要。但是必须确保源缓冲区和目标缓冲区大小至少等于或大于复制的字节数。否则,将发生缓冲区溢出。
答案 1 :(得分:2)
在这种情况下,src
和dest
数组的大小相同,因此您执行sizeof
的数组并不重要。
通常,如果使用dest
大小,那么您可以保证写入不会导致缓冲区溢出,这通常(但不总是)比读取{{{ 1}}。
然而,正如Heartbeat案例所示,阅读src
结尾可能也很严重。为了保持健壮,最好同时检查src
和src
尺寸并确认它们都是您期望的尺寸,然后再继续。
答案 2 :(得分:2)
memcpy(dst,src,len)
的第三个参数给出了要复制的字节数。
如果该字节数大于任一参数指向的内存,则 hosed。这是一个描述Heartbleed bug等技术术语,以及相当多的其他错误我有愉快的经历:-(修复。
如果您的软件开发思维模式面向内存对象,则问题中的代码模式是有效的。例如,如果你围绕着使用memcpy()
制作整个对象的精确副本的想法,我想你永远不会使用除sizeof(src)
之外的任何第三个参数。
但memcpy()
对许多其他类型的操作很有用,例如管理部分缓冲区,将不连续的数据流收集到连续的内存位置以及类似的事情。
它也会被滥用,通常没有对此进行检查。例如,在野外可能存在数万个代码片段,其中许多代码片段在嵌入式系统中,看起来像这样。
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!*/