在字符串中间写入nul字符时未检测到溢出?

时间:2014-12-10 18:47:26

标签: c buffer-overflow strcpy

说我有代码:

char* word  = malloc (sizeof(char) * 6);
strcpy(word, "hello\0extra");
puts(word);
free(word);

这个编译只是发现和Valgrind没有问题,但实际上有问题吗?好像我写入了我不拥有的记忆。

另外,一个单独的问题,但是当我用

之类的东西填充我的缓冲区时
char* word  = malloc (sizeof(char) * 6);
strcpy(word, "1234567\0");
puts(word);
free(word);

它打印出1234567并且Valgrind确实遇到了问题。做这样的事情有什么后果?它似乎每次都有效。如果这是错误的,请纠正我,但根据我的理解,另一个程序可以将记忆带过6并写入其中。如果发生这种情况,打印这个词会永远继续下去,直到遇到一个空字符?在学习C字符串时,这个角色让我感到很困惑。

4 个答案:

答案 0 :(得分:2)

第一个strcpy没关系

strcpy(word, "hello\0extra");

您创建一个char数组常量并将指针传递给strcpy。复制所有字符(包括第一个\ 0),忽略余数。

但是等等......你有一些额外的角色。这使得const数据部分更大一些。在嵌入式环境中,闪存空间很少是一个问题。但是没有运行时问题。

答案 1 :(得分:0)

strcpy(word, "hello\0extra");

这是有效的,因为第二个参数应该是格式良好的字符串,这是因为你的第6个字符\0形成一个长度为5的字符串。

strcpy(word, "1234567\0");

在这里,您正在访问您不拥有/分配的内存,因此这是一次访问冲突并可能导致崩溃。(seg fault)

答案 2 :(得分:0)

首次拨打strcpy时,NUL会插入字符串的中间位置。这意味着处理以null结尾的字符串的函数会将您的字符串视为以第一个NUL停止,并忽略字符串的其余部分。但是,free将释放所有这些并且valgrind不会报告问题,因为malloc将在分配表中存储缓冲区的长度,free将使用该条目来确定有多少要释放的字节数。换句话说,mallocfree并不意味着处理以null结尾的字符串,因此字符串中间的NUL不会影响它们。相反,free根据您在第一个位置分配的字节数来确定字符串的长度。

使用第二个示例,溢出由malloc分配的缓冲区的末尾。结果未定义。从理论上讲,您写入的内存可能已经被另一个malloc调用分配,但在您的示例中,缓冲区后内存没有任何内容,因此它是无害的。字符串处理函数将您的字符串视为以第一个NUL结尾,而不是malloc分配的缓冲区的结尾,因此打印出所有字符串。

答案 3 :(得分:0)

你的第一个问题已经有了几个好的答案。关于你的第二个问题,关于在你的malloced内存结束后写一个字节的后果:

将6个字节写入并将7写入其中会导致崩溃是值得怀疑的。 malloc喜欢在某些边界上对齐内存,因此不太可能在页面末尾给你六个字节,这样在字节7处就会出现访问冲突。但是如果你malloc 65536字节并尝试写入结束,您的程序可能会崩溃。写入无效内存会在很多时候起作用,这会使调试变得棘手,因为只有在某些情况下才会出现随机崩溃。